On 24.12.20 17:12, Saurabh Das wrote:
This causes a segfault when run with rdmd -gx:

[...]

(Tested on DMD 2.094.2 and on https://run.dlang.io/is/p0FsOQ)

If the "GC.collect()" line is commented out, it works somehow.

Please help me understand why this is happening. This is a very reduced example of an issue I am facing.

Looks like a pretty nasty bug somewhere in std.experimental.allocator or (less likely) the GC. Further reduced code:

----
import core.memory: GC;
import core.stdc.stdlib: malloc;
import std.experimental.allocator: allocatorObject;
import std.experimental.allocator.building_blocks.allocator_list: AllocatorList;
import std.stdio: writeln;
import std.typecons: Ternary;

struct Mallocator
{
    int x = 42;
    void[] allocate(size_t n) nothrow @nogc
    {
        assert(n == 56); /* memory for bookkeeping, presumably */
        void* p = malloc(n);
        assert(p !is null);
        debug writeln(&this, " malloced ", p);
        return p[0 .. n];
    }
    Ternary owns(const void[] a) pure nothrow @nogc @safe
    {
        debug writeln(&this, " owns?    ", a.ptr);
        return a.ptr is null ? Ternary.no : Ternary.yes;
    }
    bool deallocateAll() pure nothrow @nogc @safe
    {
        assert(x == 42); /* fails; should pass */
        return true;
    }
    enum alignment = 1;
}

struct List
{
    AllocatorList!(n => Mallocator()) list;
    void[] allocate(size_t n) nothrow
    {
        return list.allocate(n);
    }
    bool deallocate(void[] a) pure nothrow @nogc @safe { return false; }
    enum alignment = 1;
}

void main()
{
    auto alloc1 = allocatorObject(List());
    () { ubyte[1000] stomp; } ();
    GC.collect();
    auto gca = new int;
}
----

Apparently, something calls deallocateAll on a Mallocator instance after the memory of that instance has been recycled by the GC. Maybe allocatorObject or AllocatorList keep a reference to GC memory out of sight of the GC.

Reply via email to