Thread overview
Array operations and 'Copy on Whatever'
Aug 03, 2006
Serg Kovrov
Aug 03, 2006
Frank Benoit
Aug 03, 2006
Frank Benoit
Aug 04, 2006
Serg Kovrov
August 03, 2006
In my case it's more like 'copy on delete' then COW, but anyway... How array concatenation, assignment, etc. are handled? Is it implemented on 'library level', or on 'language level'? I mean some operations silently copies array contents, but some are not (eg. referencing). And I do not see a pattern.

In particular, did array concatenation (~, ~=) make a copy of right operand?

Consider this example:
> char[][] array_of_strings;
> 
> for (int i = 0; i < 10; i++)
> {
> 	char[] tmp = format("this is %d", i);
> 	array_of_strings ~= tmp;
> 	delete tmp; // <-- here
> }
> 
> foreach (char[] str; array_of_strings)
> 	writefln("%s", str);

When I delete tmp, strings in array_of_strings being trashed.

But on the other hand, in more simple example:
> char[] s1 = "one";
> char[] s2 = "two";
> s1 ~= s2;
> delete s2;

Deleting s2 will not affect s1.

The first one is much simplified example reproducing a problem I have encountered some time ago. As I do not understand how array operations works and cant rely them, I have to .dup near every string involved. Which seems no very smart.

So, Copy on Write, what does it mean in context of D/Phobos implementation?

Thanks
--
serg.
August 03, 2006
Serg Kovrov schrieb:

> In particular, did array concatenation (~, ~=) make a copy of right
> operand?
> 

~ allocates a new array which can hold both operands. See http://www.digitalmars.com/d/operatoroverloading.html for overloading opCat.

~= does allocate new memory only of the left-side is not big enough.

The right side is always copied.

> Consider this example:
>> char[][] array_of_strings;
>>
>> for (int i = 0; i < 10; i++)
>> {
>>     char[] tmp = format("this is %d", i);
>>     array_of_strings ~= tmp;
>>     delete tmp; // <-- here
>> }
>>
>> foreach (char[] str; array_of_strings)
>>     writefln("%s", str);
> 
> When I delete tmp, strings in array_of_strings being trashed.
> 

You concat to a char[][], which is an array of char[].
An array is a struct of a pointer and an integer for the length.

array_of_strings ~= tmp;

copies the tmp array struct to the end of array_of_strings. Perhaps array_of_strings was new allocated and copied. But you did not copy the characters of tmp. The appended array still points to where tmp also points to.

With delete tmp, you delete the characters. Here is the problem.

> But on the other hand, in more simple example:
>> char[] s1 = "one";
>> char[] s2 = "two";
>> s1 ~= s2;
>> delete s2;
> 
> Deleting s2 will not affect s1.
> 

Here you append to char[] -- not char[][].
s1 ~= s2;
does not copy the characters. Deleting s2 is now no problem.




August 03, 2006
> does not copy the characters. Deleting s2 is now no problem.
does *now* copy the characters. Deleting s2 is now no problem.
August 04, 2006
* Frank Benoit:
> array_of_strings ~= tmp;
> copies the tmp array struct to the end of array_of_strings. Perhaps
> array_of_strings was new allocated and copied. But you did not copy the
> characters of tmp. The appended array still points to where tmp also
> points to.
> With delete tmp, you delete the characters. Here is the problem.

Thanks for explaining things, Frank. Appears I was run into a shallow copy issue.