When called with an existing buffer, GC.realloc conditionally clears the newly extended part of the memory. An excerpt from druntime/src/gc/gc.d:

void *realloc(void *p, size_t size, uint bits = 0, size_t *alloc_size = null, const TypeInfo ti = null) nothrow
{
    // ...

    if (p !is oldp && !(bits & BlkAttr.NO_SCAN))
    {
        memset(p + size, 0, *alloc_size - size);
    }

    return p;
}

(Disclaimer: Although undocumented, I assume that clearing the memory is an intended feature of GC.realloc.)

With that behavior in mind, when called with null, should GC.realloc do the same thing to the entirety of the newly allocated memory?

I think it should. Otherwise, the idiom of lazily extending a memory buffer with realloc cannot be applied because one needs to memset after the first call explicitly:

import core.memory;

void main()
{
    ubyte* p = null;

    // Note that p is null for the first call
    p = cast(ubyte*)GC.realloc(p, 10);
    p = cast(ubyte*)GC.realloc(p, 20);

    // There are non-zero bytes in the first half:
    foreach (i; 0 .. 10) {
        assert(p[i] == 0); // <-- Assertion fails for some i!
    }
}

Ali

Reply via email to