On 7/28/23 11:15 AM, IchorDev wrote:
On Friday, 28 July 2023 at 11:15:31 UTC, Steven Schveighoffer wrote:
All `__gshared` does is give you storage that is accessible from all
threads,
"All __gshared does is give you [a live bomb, ready to go off at any
moment]"
!!
It seems like it's not __gshared at all, but misusing malloc with GC
pointers.
On Friday, 28 July 2023 at 14:10:16 UTC, Kagamin wrote:
Your error is using allocating the object with malloc. Since gc
doesn't see your AA, the AA is freed and you get UAF.
Friend, I think you nailed it. After adding this I haven't been able to
reproduce the segfault again:
```d
this(long n){
(){
cache = new typeof(cache);
assert(cache);
import core.memory;
core.memory.GC.addRoot(cast(void*)cache);
}();
// ...
```
It did always happen at random, so perhaps I haven't spent enough time
testing it yet, but I've gone far longer without it segfaulting than
ever before.
This is the wrong approach, it's the allocating call that should add the
root (actually a range).
For instance, the mutex is not added, that might be collected. Or if you
add more GC-pointing things into the class, that could be a problem.
What I'd do is:
```d
T alloc(T, A...)(auto ref A args){
enum classSize = __traits(classInstanceSize, T);
void* mem = core.stdc.stdlib.malloc(classSize);
assert(mem !is null, "Out of memory");
core.memory.GC.addRange(mem[0 .. classSize]);
scope(failure) {
core.memory.GC.removeRange(mem[0 .. classSize]);
core.stdc.stdlib.free(mem);
}
T inst = cast(T)mem;
inst.emplace(__traits(parameters));
return inst;
}
```
And of course, a `dealloc` that removes the range should also be added.
-Steve