(the following is teaching my grandfather to suck eggs)
Part of the problem is that writing a GC that tracks stuff residing on the C stack requires either pervasive changes to how your program does *all* its memory management, or (for things like the Chicken collector) pervasive changes to how your functions call each other and how the stack is managed. (The Boehm GC, via a triumph of inspired hackery, manages to do the first without source code changes: but it's computationally expensive as GCs go, not type-accurate, and can sometimes leave extra garbage lying around. I don't really understand why more C programs don't use the Boehm GC, though, it's a hell of a lot better than no GC at all. Perhaps C programmers *like* manual memory management? :/ )
If you can guarantee that you'll never have pointers to GCed objects anywhere on the C stack when a GC happens, it gets much much simpler, but this is a really rather harsh requirement and most systems using a GC cannot satisfy it.