bug or feature?

Oskar Linde oskar.lindeREM at OVEgmail.com
Tue Dec 5 09:42:16 PST 2006


Chris Nicholson-Sauls wrote:
> bobef wrote:
>> import std.stdio;
>> import std.string;
>>
>> void main()
>> {
>>     char[] a;
>>     char[][] b;
>>     a~="1234";
>>     b~=a;
>>     a.length=0;
>>     a~="&&";
>>     b~=a;
>>     a.length=0;
>>     a~="asdf";
>>     b~=a;
>>     writefln(join(b," "));
>> }
>>
>> //outputs "asdf as asdf"
>>
>> //if we (replace a~="..." with a="...") || (replace a.length=0 with 
>> a=null) || (replace b~=a with b~=a.dup) then it outputs "1234 && asdf"
>>
>> //i don't know if this is bug or new feature since last time i used d
> 
> Its a side-effect of a feature, I believe.  Setting an array's length to 
> 0 no longer deallocates the array.  And the ~= in this case is storing 
> the current whole /slice/ of a into b.  So its by design, but definitely 
> a potential gotcha!

It is by design and works as intended. And you are right - it is a 
gotcha that every new user to D must be aware of. The above example is 
excellent in illustrating this.

The fundamental reason for this is that D has combined the two abstract 
concepts, the array and the slice, as a hybrid: T[]

Those two concepts are unfortunately not 100 % compatible and this leads 
to problems such as the one above. I'm sure this design decision will 
come back and haunt D many times in the future.

To most people, the abstract concept of an array is "a set of elements 
with a sequential order". D's dynamic array (T[]) has the side effect of 
when changing, removing or adding elements in one array, other arrays 
/may/ be altered. This must be surprising for anyone with only an 
abstract array model in mind (a sequential set of elements).

There is only one sure way to prevent this - to strictly and manually 
employ Copy on Write for all cases except when you can be sure that the 
memory area used by the array is unique and writable. There is no help 
from the compiler. D will not keep reference counts, give compile time 
or run time warnings or even hold your hand. It even prevents you from 
implementing your own automatic reference counts. The mantra is "If 
unsure, dup."

The above code violates CoW twice, and thus the unexpected behavior.

/Oskar



More information about the Digitalmars-d-bugs mailing list