AA vs __gshared
Steven Schveighoffer
schveiguy at gmail.com
Fri Jul 28 21:22:01 UTC 2023
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
More information about the Digitalmars-d-learn
mailing list