www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - GC.realloc() fails to initialize some part of the memory

reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
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
Jul 16 2014
parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 07/16/2014 05:44 PM, Ali Çehreli wrote:


Some part of my analysis was wrong. The issue is only when GC.realloc is 
called with null, in which case it allocates memory.

I asked the new question of whether that allocated memory should be 
cleared here:

   http://forum.dlang.org/thread/lq9gji$2sg7$1 digitalmars.com

Ali
Jul 17 2014