[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