GC.realloc() fails to initialize some part of the memory

Ali Çehreli via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Wed Jul 16 17:44:19 PDT 2014


Here is an interesting case related to an undocumented feature of 
GC.realloc(). Although I think there is a bug, I don't want to create a 
bug report yet because the feature is not even documented. :)

First, here is its most recent definition 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
     {
         size_t localAllocSize = void;
         auto oldp = p;
         if(alloc_size is null) alloc_size = &localAllocSize;

         // Since a finalizer could launch a new thread, we always need 
to lock
         // when collecting.  The safest way to do this is to simply 
always lock
         // when allocating.
         {
             gcLock.lock();
             p = reallocNoSync(p, size, bits, *alloc_size, ti);
             gcLock.unlock();
         }

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

         return p;
     }

As can be seen by that memset, it conditionally clears the newly 
extended part of the memory area. (This is a bonus feature of Phobos 
over C's standard library as the documentation of C's realloc() says 
"newly allocated memory will be uninitialized".) However, memset() above 
starts from 'p + size' where 'size' is the newly requested size. As a 
result, the area between the old size and the new size are left 
uninitialized.

The question is especially interesting and easier to demonstrate when 
'p' is null because in that case although GC.realloc() tries to work 
like GC.calloc(), it actually ends up working like GC.malloc().

The output of the following program demonstrates that the initial part 
of the allocated memory is uninitialized. (I've gotten paranoid and 
removed the output of running it on my computer; there could be credit 
card numbers in there. :p)

import std.stdio;
import core.memory;

void main()
{
     const length = 20;
     auto p = GC.realloc(null, length);
     writefln("%2s: %(%02x %)", length, p[0 .. length]);
}

Ali


More information about the Digitalmars-d-learn mailing list