Append to dynamic array that was allocated via calloc

Mike Parker via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Tue Jul 25 06:24:36 PDT 2017


On Tuesday, 25 July 2017 at 12:40:13 UTC, John Burton wrote:
> I can create a "slice" using non-gc allocated memory.
>
>         int* ptr = cast(int*)calloc(int.sizeof, 10);
>         int[] data = ptr[0..10];
>
> If I don't want a memory leak I have to call free(ptr) 
> somewhere as it won't be GC collected when data or ptr go out 
> of scope. I presume there is nothing wrong with doing the 
> above, other than perhaps there being better ways (and the 
> memory leak if not free'd)
>
> If I then write this :-
>
>         data ~= 1;
>
> What happens? It seems to successfully append an extra value to 
> the array. It appears to "work" when I try it in my compiler 
> but I don't understand how. Will this be trying to write beyond 
> the memory I calloc'ed?

This should give you the answer:

writefln("Before: ptr = %s capacity = %s", slice.ptr, 
slice.capacity);
slice ~= 1;
writefln("After: ptr = %s capacity = %s", slice.ptr, 
slice.capacity);

It shows that before the append, the capacity is 0. That 
indicates that any append will cause a new allocation -- from the 
GC. The next writefln verifies this by showing a different value 
for ptr and a new capacity of 15.

In order for this to work, you'll need to manually manage the 
length and track the capacity yourself. If all you want is to 
allocate space for 10 ints, but not 10 actual ints, then 
something like this:

size_t capacity = 10;
int* ints = cast(int*)malloc(int.sizeof * capacity);
int[] slice = ints[0 .. 10];
slice.length = 0;
slice ~= 1;
--capacity;

Then reallocate the array when capacity reaches 0. Or just use 
std.container.array.Array which does all this for you.



More information about the Digitalmars-d-learn mailing list