Memory leak with dynamic array
Steven Schveighoffer
schveiguy at yahoo.com
Sat Apr 10 17:43:44 PDT 2010
On Sat, 10 Apr 2010 18:17:12 -0400, bearophile <bearophileHUGS at lycos.com>
wrote:
> This can help confuse your mind a bit:
>
> import std.stdio: writeln;
> void main() {
> {
> int[] arr = [0, 1, 2, 3, 4, 5, 6].dup;
> int[] slice = arr[2 .. 4];
> writeln("arr, slice: ", arr, " | ", slice); // arr, slice: 0 1 2
> 3 4 5 6 | 2 3
> slice ~= 10; slice ~= 20;
> writeln("arr.capacity, slice.capacity: ", arr.capacity, " ",
> slice.capacity); // arr.capacity, slice.capacity: 7 7
> writeln("arr, slice: ", arr, " | ", slice); // arr, slice: 0 1 2
> 3 4 5 6 | 2 3 10 20
> }
>
> {
> int[] arr = [0, 1, 2, 3, 4, 5, 6].dup;
> int[] slice = arr[2 .. 4];
> writeln("arr, slice: ", arr, " | ", slice); // arr, slice: 0 1 2
> 3 4 5 6 | 2 3
>
> slice.assumeSafeAppend;
> slice ~= 10; slice ~= 20; // causes stomping
> writeln("arr.capacity, slice.capacity: ", arr.capacity, " ",
> slice.capacity); // arr.capacity, slice.capacity: 0 5
> writeln("arr, slice: ", arr, " | ", slice); // arr, slice: 0 1 2
> 3 10 20 6 | 2 3 10 20
> slice ~= 30; slice ~= 40;
> writeln("arr.capacity, slice.capacity: ", arr.capacity, " ",
> slice.capacity); // arr.capacity, slice.capacity: 7 7
> writeln("arr, slice: ", arr, " | ", slice); // arr, slice: 0 1 2
> 3 10 20 30 | 2 3 10 20 30 40
> }
> }
>
>
> The slice.capacity = 7 in the first case is just a coincidence, it's
> the result of the overallocation.
Yes, to allocate an array of 4 integers, you need 16 bytes, but there
needs to be a padding byte to prevent cross-block pointer problems, so it
uses a 32-byte block. The 32-byte block also needs a padding byte, so
really you can only put in 7 elements, not 8.
> But I don't know why arr.capacity is zero and then seven in the second
> and third case.
0 means if you append to the array, it will reallocate. It will return 0
for stack-allocated arrays also. This makes sense since the slice has
taken over the "allocated" length of the block. Essentially, capacity
indicates how many elements can be appended. The function gives up and
returns 0 if it determines the array does not end at the allocated part of
a block. Technically, I could return the length of the array, but I'm not
sure whether that is as useful.
For fun, add one more element to slice, and the arr will now have a valid
capacity :)
FYI, using arr after assuming safe append on the slice is undefined.
-Steve
More information about the Digitalmars-d-learn
mailing list