Pointers or copies?

Chris Nicholson-Sauls ibisbasenji at gmail.com
Fri Dec 22 06:41:03 PST 2006


Frits van Bommel wrote:
> Chris Nicholson-Sauls wrote:
>> Frits van Bommel wrote:
>>> Chris Nicholson-Sauls wrote:
>>>> void drop (T) (inout T[] haystack, size_t index)
>>>> in {
>>>>   assert(index < haystack.length, ".drop() called with index greater 
>>>> than array length");
>>>> }
>>>> body {
>>>>   if (index != haystack.length - 1) {
>>>>     memmove(&(haystack[index]), &(haystack[index + 1]), T.sizeof * 
>>>> (haystack.length - index));
>>>>   }
>>>>   haystack.length = haystack.length - 1;
>>>> }
>>>
>>> Doesn't that move one element from beyond the end of the array?
>>>
>>> Array [0, 1, 2], drop element at index 1:
>>>     memmove(&(array[1]), &(array[2]), int.sizeof * (3-1));
>>> Moves 2 elements, starting at the 3rd element (element at index 2) of 
>>> a 3-element array...
>>
>> Doesn't seem to.  Illustrative program:
>>
>> # import cashew .utils .array ;
>> # import std           .stdio ;
>> #
>> # struct Foo {
>> #   int[] alpha = [0, 1, 2],
>> #         beta  = [3, 4, 5];
>> # }
>> #
>> # void main () {
>> #   Foo foo ;
>> #
>> #   writefln("foo.alpha == ", foo.alpha);
>> #   writefln("foo.beta  == ", foo.beta );
>> #
>> #   foo.alpha.drop(1U);
>> #
>> #   writefln("foo.alpha == ", foo.alpha);
>> #   writefln("foo.beta  == ", foo.beta );
>> # }
>>
>> For me this output:
>> foo.alpha == [0,1,2]
>> foo.beta  == [3,4,5]
>> foo.alpha == [0,2]
>> foo.beta  == [3,4,5]
>>
>> Which seems to imply the data after alpha isn't being touched.  That 
>> said, I'll try changing it anyhow.  Just in case.
> 
> How do you know it isn't touched? Just because it doesn't segfault 
> doesn't mean it isn't accessing beyond array bounds...
> In fact, as long as the int after alpha is readable (i.e. the memory is 
> mapped) you won't see a difference with that code.
> 
> You'd probably see a difference if you kept a copy of alpha around and 
> wrote that to output as well, though. (since the length of the copy 
> doesn't get adjusted)
> In fact, I just tried that and the last element of alpha is overwritten 
> by the first element of beta. This shouldn't happen if memmove() is 
> called with the correct parameters.

Well, there we are then.  :)

> Another way to see this without keeping references to arrays being 
> modified (which is arguably bad style) is the following:
> Replace the last argument of the memmove call with
> 'T.sizeof * (haystack.length - index - 1)' and notice your code above 
> gives the exact same result...

Actually, this is exactly what I have done.  Its in the repository now.

-- Chris Nicholson-Sauls



More information about the Digitalmars-d mailing list