orangeduck/tgc logo

orangeduck/tgc

Free

A Tiny Garbage Collector for C

FreeFree tier
Type
Open Source

About orangeduck/tgc

tgc is a tiny garbage collector for C, written in approximately 500 lines of code. It implements a conservative, thread-local, mark-and-sweep garbage collector that automatically frees memory allocated via tgc_alloc and related functions once it becomes unreachable. The library supports destructors, manual freeing, pausing and resuming the collector, and provides functions like tgc_calloc, tgc_realloc, and tgc_alloc_opt. Reachability is determined by pointers on the stack or in other tgc-allocated memory, with specific limitations (e.g., pointers must point to the start of an allocation; pointers from static data, malloc'd memory, or other threads do not keep allocations alive). It is based on the Cello Garbage Collector and is suitable for C programs that want automatic memory management without a heavy dependency.

Key Features

Conservative, thread-local mark-and-sweep garbage collection
Automatic memory reclamation for allocations made with tgc_alloc and friends
Support for destructors via tgc_set_dtor
Manual memory freeing with tgc_free
Pause and resume functionality (tgc_pause / tgc_resume)
Allocation functions: tgc_alloc, tgc_calloc, tgc_realloc, tgc_alloc_opt
Iteration can be triggered manually via tgc_run
Runs in about 500 lines of C code

Pros & Cons

Pros
  • Very small codebase (~500 lines) making it easy to understand and audit
  • Simple API with only a few functions
  • Automatic memory management reduces risk of memory leaks and dangling pointers
  • Thread-local design avoids locking overhead in single-threaded or per-thread contexts
  • Supports destructors for cleanup when memory is freed
  • Open source and permissively licensed
Cons
  • Not thread-safe across threads (thread-local only – each thread must start its own collector)
  • Conservative collector may have false positives (keep memory alive unnecessarily)
  • Reachability limitations: pointers must point exactly to the start of an allocation; pointers from static data, malloc'd memory, or other threads do not prevent collection
  • Only works with memory allocated via tgc_alloc family – mixing with malloc/calloc/realloc can lead to issues
  • No support for weak references or finalization ordering beyond destructors

Best For

Adding automatic garbage collection to C programs to avoid manual memory managementSmall-scale or embedded projects where a full GC like Boehm would be too largeEducational purposes to understand how a simple mark-and-sweep GC worksPrototyping or scripting-style C code where memory leaks are a concern

FAQ

What is tgc?
tgc is a tiny garbage collector for C. It is a conservative, thread-local, mark-and-sweep garbage collector written in about 500 lines of code, based on the Cello Garbage Collector.
How do I use tgc in my program?
Include 'tgc.h', call tgc_start() at the beginning of a thread, replace malloc/free with tgc_alloc/tgc_free, and call tgc_stop() at the end. The collector will automatically free memory that becomes unreachable.
Does tgc support destructors?
Yes, you can register a destructor for an allocation using tgc_set_dtor or allocate with tgc_alloc_opt and pass a destructor function. The destructor runs before the memory is freed.
What memory is considered reachable by tgc?
Memory is reachable if a pointer points to the start of the allocation, located on the stack at least one function call deeper than tgc_start, or in another tgc-allocated memory. Pointers from static data, malloc, or other threads do not keep allocations alive.
Can I pause and resume the garbage collector?
Yes, tgc provides tgc_pause() and tgc_resume() to temporarily stop automatic collection during memory-intensive operations.