GC issue? List.pool overwritten by allocated object

Denis Feklushkin feklushkin.denis at gmail.com
Fri May 16 20:26:44 UTC 2025


On Friday, 16 May 2025 at 10:42:36 UTC, Denis Feklushkin wrote:
> On Wednesday, 14 May 2025 at 09:11:13 UTC, Denis Feklushkin 
> wrote:
>
>> Okay, I think the question can be considered closed
>
>
> However, I am still on this issue! :(

I still think this is may be a druntime issue. And it's probably 
not about TLS.

I discovered the [rr](https://github.com/rr-debugger/rr) tool 
that allows quickly create and replay repeatable replays in the 
gdb (its built-in system works very slowly). So now there's no 
need to run gdb many times and carefully examine everything. `rr` 
available in Debian, but that version doesn't work with my code - 
some kind of tick counting error, seems because video driver 
used), but self-compiled one works fine.

So, after playing and rewind few times I clearly see:

I made sure that malloc uses switched "arenas" as soon as threads 
appear - this mechanism is built into glibc and enabled 
automatically when second pthread created.

I also tried replacing `free(void*)` symbol with my own empty 
stub to make sure that nothing was freed definitely and someone 
didn't get the used piece again. It didn't help.

Vulkan library quite legitimately allocates some memory for its 
needs, uses it, and this memory contains that memory piece where 
the issue occurs. I don't know why Valgrind answered (evasively) 
that this memory had not been allocated before.

Next, when executing on the D side, GC's pool of small 
allocations (of size 32) is exhausted. And then some magic 
happens in the gc.d code using recoverPool near 
`SmallObjectPool.allocPage()`, which I do not fully understand. 
(Obliviously, this is necessary to reuse the memory that was 
previously allocated.)

As a result, a new `List` is formed without `malloc()` call. This 
list contains a pointer to the some pool. Apparently, this memory 
is taken from a previously used pool. But at the same time, the 
memory that this pointer points to looks as has never been 
touched by any D code. I haven't figured out why this is so yet. 
Perhaps there is some error in calculating pointers.

Also, during inside of `allocPage`, execution flow gets to the 
line:
```
void* p = baseAddr + pn * PAGESIZE;
```
but at same time baseAddr == 0xf0f0f0f0f0f0f0f0f0 (result of 
MEMSTOMP)


More information about the Digitalmars-d mailing list