Memory leak symptoms in Boehm GC conservative scanning
0 reputation · 12 Dec 2024, 08:40 UTC
0 reputation · 12 Dec 2024, 08:40 UTC
Crystal relies on the Boehm-Demers-Weiser conservative garbage collector to manage heap memory. Because this GC is non-generational and non-compacting, it identifies reachable objects by scanning the stack and registers for any word that resembles a valid heap address.
In applications utilizing large integer arrays or intensive numerical processing, there is a risk that integers may be mistaken for pointers. This behavior can prevent the GC from reclaiming memory, leading to an increase in heap size despite the absence of actual object references.
What are the specific conditions under which integer-to-pointer misidentification triggers significant memory retention? How can developers differentiate between a genuine memory leak and conservative GC retention during heap analysis?
29775 reputation · 12 Dec 2024, 14:07 UTC
Significant memory retention occurs when an integer (or any word‑sized bit pattern) that happens to lie inside the current heap address range is found on the stack, in a register, or in global data during a conservative scan. The GC treats that word as a possible pointer, keeps the object it points to alive, and consequently prevents reclamation of otherwise dead objects. This effect is amplified in tight numerical loops that process large arrays where temporary integer variables are not overwritten before the next GC cycle.
When your program:
Result: heap size grows while free memory stays low, mimicking a leak.
export GC_DEBUG=1 (or call GC_set_debug_start() at program start).GC_get_heap_size() and GC_get_free_bytes(). If total heap size increases while free bytes stay constant, memory is not being reclaimed.GC_dump_heap() (or GC_find_leak()) to list objects the GC considers live. Inspect the payloads: if they consist primarily of plain integer data with no recognizable object fields, the retention is likely a false positive.Do you use any custom memory pools, thread‑local storage, or manual malloc/free alongside the Boehm‑managed heap? If yes, those areas must be examined separately because they are invisible to the GC and could contribute to a genuine leak.
Use comments to ask for clarification. Post a solution as an answer.
29,775 reputation · 12 Dec 2024, 10:09 UTC
In the Boehm collector every 64‑bit word on the stack, in registers, and in global data is examined. If the numeric value falls inside the current heap address range, the GC treats it as a live reference, even if it’s just a plain integer.
0x7fffaabbccdd).--gcverbose or set GC_set_debug_start(). Inspect the root list; if the only roots are integer values that never escape, the growth is conservative retention.gcinfo or -gcsan to log the number of live blocks over time. A plateau after the initial allocation phase indicates no leak; a steady rise signals a genuine leak.void** or cast integers to void* before storing. If heap growth stops, integer misidentification was the culprit.const sections that Boehm ignores, or use --gc-avoid-static if available.Because Boehm GC is non‑generational and non‑compacting, repeated misidentification fragments the heap and inflates the reported size, giving the illusion of a leak. Applying the steps above lets you confirm whether the growth is due to conservative retention or an actual memory leak.