Confusing behaviour of array member assignment when calling local function

Steven Schveighoffer schveiguy at gmail.com
Sun Jan 5 02:33:51 UTC 2025


On Saturday, 4 January 2025 at 23:11:58 UTC, Sahan Fernando wrote:
> Hello all,
>
> I've encountered an unexpected behaviour in the D language, 
> where assigning the result of a function that grows an array to 
> a value in that array ends up modifying the old memory used 
> previously by that array. This seems counterintuitive to me in 
> the sense that it feels logical that the lvalue to be assigned 
> to should be evaluated after the function has been evaluated, 
> but this behaviour implies that part of the lvalue was 
> evaluated before the function.
>
> A minimal reproduction of the issue I'm describing is attached 
> below:
>
> ```d
> import std.exception;
>
> void main() {
>     auto v = new ulong[1];
>     size_t appendAndGetLength() {
>         v ~= [10, 10, 10, 10, 10, 10, 10, 10, 10, 10];
>         return v.length;
>     }
>     v[0] = appendAndGetLength();
>     // Works if we do the following instead
>     // auto v0 = appendAndGetLength();
>     // v[0] = v0;
>     enforce(v[0] == v.length);
> }
> ```

So what is happening here is the left side of the assignment is 
being evaluated first. Then the right side. The right side alters 
`v` by appending (it must reallocate to accomodate the new 
values), and therefore you assign to the *old* `v`.

This can be demonstrated:

```d
void main() {
     auto v = new ulong[1];
     auto oldv = v;
     size_t appendAndGetLength() {
         v ~= [10, 10, 10, 10, 10, 10, 10, 10, 10, 10];
         return v.length;
     }
     v[0] = appendAndGetLength();
     enforce(oldv.ptr !is v.ptr);
     enforce(oldv[0] == v.length);
}
```

A dynamic array (or slice) is simply a pointer and a length. It 
is *not* a reference into an array object (many other languages 
are like this, D is not).

You can read more about how arrays work here: 
https://dlang.org/articles/d-array-article.html

-Steve


More information about the Digitalmars-d mailing list