any news on const/invariant?

Regan Heath regan at netmail.co.nz
Tue Nov 27 08:31:27 PST 2007


Leandro Lucarella wrote:
> Frank Benoit, el 27 de noviembre a las 11:01 me escribiste:
>> Regan Heath schrieb:
>>> Walter Bright wrote:
>>>> Regan Heath wrote:
>>>>> void foo(char[] pbuffer)
>>>>> {
>>>>>   //assume this causes reallocation
>>>>>   //assume there is no more space in place
>>>>>   pbuffer ~= "a";
>>>>> }
>>>>>
>>>>> void main()
>>>>> {
>>>>>   char[] buffer = "test".dup;
>>>>>   foo(buffer);
>>>>>   buffer[0] = 'a' //crash
>>>>> }
>>>>>
>>>>> Right?
>>>> No. foo() modifies its copy of pbuffer, which is not the same as buffer.
>>> Yes, but the underlying memory is reallocated so buffer no longer points
>>> to valid memory, right?
>>>
>>> Regan
>> You missed a semicolon, so it does not compile :)
>> Realloc does not destroy the original buffer. So your foo just make a
>> modified copy, that is not visible for the caller. buffer will stay
>> unchanged.
> 
> I think you are missing an important point here: 

In fact I missed it too!

I was actually more concerned that buffer would not longer point to 
valid memory.  I eventually figured out that D does not reallocate the 
original pointer unless it can reallocate in place.  If it cannot 
reallocate in place it creates a new copy of the data.

> This could lead to some hard to find bugs, because of the lack of
> explicitness and non-determinism (so to speak) where pbuffer ~= "a"; could
> lead or not to reallocation (or the fact that pbuffer[0] = 'a' will
> survive the local function and concatenation *may* survive or may not).

Actually concatenation wont survive either because buffer.length is not 
changed by the concatenation.  eg.

void foo(char[] pbuffer)
{
   pbuffer ~= "a";
}
void main()
{
   char[] buffer = "test".dup;
   foo(buffer);
   writefln(buffer);
}

This will always output "test".  It would only become non-deterministic 
if you coded:

void main()
{
   char[] buffer = "test".dup;
   foo(buffer);
   buffer = buffer.ptr[0..buffer.length+1]
   writefln(buffer);
}

as 99 times out of 100 you would get "testa" now, but the one time it 
cannot do an in place reallocation in foo there will be no "a" at the 
memory address following "test".

As for:

void foo(char[] pbuffer)
{
   pbuffer[0] = 'a';
}

this modification survives, but can be prevented with:

void foo(invariant(char)[] pbuffer)
{
   pbuffer[0] = 'a';  //error
}

and "string" will continue to be an alias for invariant(char)[] I imagine.

In short, ignore me I was throwing crimson coloured fish in the air.

Regan



More information about the Digitalmars-d mailing list