static array internal & dangling reference

cym13 via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sat Nov 12 02:45:23 PST 2016


On Saturday, 12 November 2016 at 10:33:05 UTC, Picaud Vincent 
wrote:
> Hi all,
> Still learning... This time what surprised me is how static 
> arrays work.
> I assume (is it true?) that for efficiency reason static size 
> arrays like int[10] are on the stack and do not involve dynamic 
> memory allocation:

Yes, they're on the stack. They're just like a C-array: a plain 
region with items in sequence.

> First surprise: it is possible to share a static array:
>
> void main() {
>
>   int[10] sa;
>   foreach(int i, ref sa_i;sa){
>     sa_i=i;
>   }
>   writeln("\n vect init sa",sa);
>
>   int[] sb=sa[3..6];       // <- did not think it was possible
>   sb[2]=100;
>
>   writeln("\n vect sa ",sa);
>   writeln("\n vect sb ",sb);
> }

Note that sb is a slice: it's just a pointer and a length. A 
pointer to what? To the third element of sa because that's the 
beginning of the slice.

> which prints:
>
>  vect init sa[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>
>  vect sa [0, 1, 2, 3, 4, 100, 6, 7, 8, 9]  // <- sa and sb are 
> really shared

Well, sure, sb is a pointer to part of sa so you're accessing sa 
by reference when making use of sb (well, with an offset that is).

>  vect sb [3, 4, 100]
>
> Second surprise: I tried to create a dangling reference with:
>
> int[] f()
> {
>   int[10] sa;
>   foreach(int i, ref sa_i;sa){
>     sa_i=i;
>   }
>   int[] sb=sa;
>   return sb;
> }
>
> void f_test()
> {
>   auto sb=f();
>   sb[2]=100; // I expected an "invalid access" (it points to 
> "sa", a local variable)
> }
>
> However calling f_test seems ok and valgrind tool does not 
> complain...

Printing the address of sa[2] and sb[2] in f() as well as the 
address of sb[2] in f_test() we see that they're all the same. So 
yes you are using a dangling reference. It only gives you the 
good result because you haven't overwritten that part of the 
stack yet. Demonstration:

void f_test() {
     auto sb=f();
     sb[2] = 100;
     writeln(sb[2]); // prints 100
     int test[100];
     writeln(sb[2]); // prints 0
}

I don't know why valgrind isn't panicking.

> So my questions are:
> 0/ does I miss something? (in C++ for sure you create a 
> dangling pointer)
> 1/ what is the internal mechanism for that? Is the GC involved? 
> Performance impact?
> 2/ any link describing this in more details is welcome
>
> Thank you




More information about the Digitalmars-d-learn mailing list