GC issue? List.pool overwritten by allocated object

Denis Feklushkin feklushkin.denis at gmail.com
Mon May 12 15:31:34 UTC 2025


Hi!

It seems I have encountered a bug that is hard to understand and 
fix without knowlenge of the GC internals. But I have some code 
that reproduces the problem well. I made a branch so that 
everyone can try it (see below)

Usual (not very beautiful, yes) code that I do for fun. During 
run it creates and destroys various objects, everything is as 
usual, it does nothing strange, no manipulations with the GC, 
except collect() called once or twice, and I also often call 
destroy(). Also no multithreading, but Vulkan API is used and it 
implicitly creates threads. On sucessful run code displays window 
with two rotating pictures.

For small objects my code regularly and deterministically gets 
into a situation when at some point the value of 
core.internal.gc.impl.conservative.gc.List.pool pointer is 
overwritten by garbage. Using gdb I tracked that after 
appropriate List.pool is created and written, at some time this 
piece of memory is overwritten by a newly allocated D object. As 
result, garbage value of List.pool is used at next 
gc.Gcx.smallAlloc() call and SIGSEGV occurs.

(For tracking I used gdb option "set scheduler-locking on" - it 
seems that this is what makes List* address the same every time, 
which makes debugging much easier.)

I tried to turn on --d-debug=INVARIANT --d-debug=SENTINEL 
--d-debug=MEMSTOMP for druntime. All these options confirming the 
problem. Sometimes issue shifted either to a newly added GC 
invariant as assert error, assert(*sentinel_pre(p) == 
SENTINEL_PRE) error, or problem manifests itself not immediately 
after launch, but after a few seconds of the application's 
operation when allocating object. But it still repeats every time 
- that is, this is not a heisenbug.

Perhaps all this is the result of an error somewhere else, which 
results in this behavior. That is, if some my code (or third 
party) corrupts something that affects to allocation? But it 
seems that I do not do any hacks, any manipulations with 
pointers, etc.

Everything is reproduced on DMD and LDC. I use LDC for debugging 
because it is easy to switch between different druntimes in it.

I couldn't reduce code to highlight issue. So here is how to 
reproduce:

$ git clone --branch=move_to_ldc2 
https://github.com/denizzzka/pukan.git
(ensure you are on commit 
f7e5293cdeb14da911bc337e281378b92ca39f25)
$ cd pukan #important!
$ dub run

For now I tested my code only on Linux, so it might not work in 
Windows at all.
Issue is reproduceable on druntime supplied with:
DMD64 D Compiler v2.111.0
LDC 1.40.1



More information about the Digitalmars-d mailing list