www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Array operations and 'Copy on Whatever'

reply Serg Kovrov <kovrov no.spam> writes:
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.
Aug 03 2006
parent reply Frank Benoit <keinfarbton nospam.xyz> writes:
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.
Aug 03 2006
next sibling parent Frank Benoit <keinfarbton nospam.xyz> writes:
 does not copy the characters. Deleting s2 is now no problem.
does *now* copy the characters. Deleting s2 is now no problem.
Aug 03 2006
prev sibling parent Serg Kovrov <kovrov no.spam> writes:
* 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.
Aug 04 2006