[Issue 429] New: Unable to distinguish between empty and uninitialized dynamic arrays

d-bugmail at puremagic.com d-bugmail at puremagic.com
Wed Oct 11 17:31:46 PDT 2006


http://d.puremagic.com/issues/show_bug.cgi?id=429

           Summary: Unable to distinguish between empty and uninitialized
                    dynamic arrays
           Product: D
           Version: unspecified
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: minor
          Priority: P4
         Component: Phobos
        AssignedTo: bugzilla at digitalmars.com
        ReportedBy: ddparnell at bigpond.com


When setting the length of a dynamic array to zero, phobos (gc) also frees the
RAM for that array. This means that applications cannot tell an uninitialized
array from an empty array. It also means that an application cannot reserve RAM
in the generic case. 

Note that reducing the length of an array to a value greater than zero does not
cause this behaviour, instead all the RAM for the array is reusable when the
application later increases the length.

Example:
   int[] test;
   test.length = 10;
   // Show address of array start and its length (10)
   writefln("%s %s", cast(uint)test.ptr, test.length);

   test.length = 1;
   // Show address of array start and its length (1)
   writefln("%s %s", cast(uint)test.ptr, test.length);

   test.length = 8;
   // Show address of array start and its length (8)
   writefln("%s %s", cast(uint)test.ptr, test.length);

   test.length = 0;
   // Shows 0 and 0!
   writefln("%s %s", cast(uint)test.ptr, test.length);

If an application needs to reset an array to the uninitialized state then it
can do 'arrayname = null;'.

The change to gc.d could be done as a two-line change ...

extern (C)
byte[] _d_arraysetlength2(size_t newlength, size_t sizeelem, Array *p, ...)
in
{
    assert(sizeelem);
    assert(!p.length || p.data);
}
body
{
    byte* newdata;

    debug(PRINTF)
    {
        printf("_d_arraysetlength2(p = %p, sizeelem = %d, newlength = %d)\n",
p, sizeelem, newlength);
        if (p)
            printf("\tp.data = %p, p.length = %d\n", p.data, p.length);
    }

    if (newlength)
    {
        version (D_InlineAsm_X86)
        {
            size_t newsize = void;

            asm
            {
                mov     EAX,newlength   ;
                mul     EAX,sizeelem    ;
                mov     newsize,EAX     ;
                jc      Loverflow       ;
            }
        }
        else
        {
            size_t newsize = sizeelem * newlength;

            if (newsize / newlength != sizeelem)
                goto Loverflow;
        }
        //printf("newsize = %x, newlength = %x\n", newsize, newlength);

        size_t size = p.length * sizeelem;
        if (p.data)  // <<-CHG
        {
            newdata = p.data;
            if (newlength > p.length)
            {
                size_t cap = _gc.capacity(p.data);

                if (cap <= newsize)
                {
                    newdata = cast(byte *)_gc.malloc(newsize + 1);
                    newdata[0 .. size] = p.data[0 .. size];
                }
            }
        }
        else
        {
            newdata = cast(byte *)_gc.malloc(newsize + 1);
        }

        va_list q;
        va_start!(Array *)(q, p);       // q is pointer to initializer

        if (newsize > size)
        {
            if (sizeelem == 1)
            {
                //printf("newdata = %p, size = %d, newsize = %d, *q = %d\n",
newdata, size, newsize, *cast(byte*)q);
                newdata[size .. newsize] = *(cast(byte*)q);
            }
            else
            {
                for (size_t u = size; u < newsize; u += sizeelem)
                {
                    memcpy(newdata + u, q, sizeelem);
                }
            }
        }
    }
    else
    {
      newdata = p.data;  //<<-CHG
    }

    p.data = newdata;
    p.length = newlength;
    return newdata[0 .. newlength];

Loverflow:
    _d_OutOfMemory();
}


-- 




More information about the Digitalmars-d-bugs mailing list