Thread overview
not expected pointers for struct members from foreach
Oct 09, 2012
deed
Oct 09, 2012
bearophile
Oct 09, 2012
deed
Oct 09, 2012
H. S. Teoh
Oct 10, 2012
bearophile
Oct 10, 2012
deed
October 09, 2012
import std.stdio;


struct Test
{
    static Test[]  objects;
    static Test*[] psObject;
    static int[]   ints;
    static int*[]  psInt;
	
    int  a;
    int	 b;
    int* pa;
	
    this(int a)
    {
        this.a = a;
        this.pa = &this.a;
        this.b = 2 * a;
		
        objects  ~= this;
        psObject ~= &this;
        ints     ~= b;
        psInt    ~= &this.b;
    }
}


void main()
{
    Test(20);               // /*
    Test(21);               //  * As expected.
    Test(22);               //  */
	
    foreach(int i; 0 .. 3)  // /*
    {                       //  * What happens here?
        Test(30 + i);       //  *
    }                       //  */
	
    Test.psObject.writeln;
        // Prints [7FFFA4E84530, 7FFFA4E84540, 7FFFA4E84550,
        //         7FFFA4E84570, 7FFFA4E84570, 7FFFA4E84570]
        // Why are the three last adresses the same?

    Test.ints.writeln;
        // Prints [40, 42, 44, 60, 62, 64]
        // As expected.

    Test.psInt.writeln;
        // Prints [7FFFA4E84534, 7FFFA4E84544, 7FFFA4E84554,
        //         7FFFA4E84574, 7FFFA4E84574, 7FFFA4E84574]
        // Again, why are the three last adresses the same?
}
October 09, 2012
deed:

>         // Again, why are the three last adresses the same?

The D language and its compiler is acting correctly here, so the output you see is correct. All those structs are allocated on the stack. The first three Test are allocated on the stack. In the loop it allocates the first struct on the stack, and it gets destroyed. Then when the successive loop enters, it creates a new struct, and it uses the same stack space.

See:

import std.stdio;

struct Test {
    static Test*[] psObject;
    int x;
    this(int a) {
        x = a;
        psObject ~= &this;
    }
    ~this() {
        writeln(x);
    }
}

void main() {
    Test(0);

    foreach (i; 1 .. 3)
        Test(i);

    Test.psObject.writeln();
}


0
1
2
[12FE48, 12FE54, 12FE54]

Bye,
bearophile
October 09, 2012
On Tuesday, 9 October 2012 at 16:21:47 UTC, bearophile wrote:
> deed:
>
>>        // Again, why are the three last adresses the same?
>
> The D language and its compiler is acting correctly here, so the output you see is correct. All those structs are allocated on the stack. The first three Test are allocated on the stack. In the loop it allocates the first struct on the stack, and it gets destroyed. Then when the successive loop enters, it creates a new struct, and it uses the same stack space.
>
> See:
>
> import std.stdio;
>
> struct Test {
>     static Test*[] psObject;
>     int x;
>     this(int a) {
>         x = a;
>         psObject ~= &this;
>     }
>     ~this() {
>         writeln(x);
>     }
> }
>
> void main() {
>     Test(0);
>
>     foreach (i; 1 .. 3)
>         Test(i);
>
>     Test.psObject.writeln();
> }
>
>
> 0
> 1
> 2
> [12FE48, 12FE54, 12FE54]
>
> Bye,
> bearophile

Meaning struct pointers are unusable or at least highly
unreliable?
October 09, 2012
On Wed, Oct 10, 2012 at 12:59:08AM +0200, deed wrote:
> On Tuesday, 9 October 2012 at 16:21:47 UTC, bearophile wrote:
> >deed:
> >
> >>       // Again, why are the three last adresses the same?
> >
> >The D language and its compiler is acting correctly here, so the output you see is correct. All those structs are allocated on the stack. The first three Test are allocated on the stack. In the loop it allocates the first struct on the stack, and it gets destroyed. Then when the successive loop enters, it creates a new struct, and it uses the same stack space.
[...]
> Meaning struct pointers are unusable or at least highly unreliable?

No, meaning if you want the struct to survive the end of the scope it's declared in, you need to use new:

	struct S {
		// ... stuff
	}

	void main() {
		S*[] ptrs;

		foreach (i; 0..10) {
			auto s = new S;
			ptrs ~= s;	// this is OK
		}

		// foreach (i; 0..10) {
		//	S s;
		//	ptrs ~= &s;	// this is NOT OK
		//}
	}


T

-- 
Let X be the set not defined by this sentence...
October 10, 2012
deed:

> Meaning struct pointers are unusable or at least highly
> unreliable?

Struct pointers are useful and reliable, but before using them you need to know the difference between heap and stack, what a stack frame is, and how structs are handled when they are on the stack. Learning the basics of such things ideas requires only few minutes and it will be useful for many years.

Bye,
bearophile
October 10, 2012
> Struct pointers are useful and reliable, but before using them you need to know the difference between heap and stack, what a stack frame is, and how structs are handled when they are on the stack. Learning the basics of such things ideas requires only few minutes and it will be useful for many years.
>
> Bye,
> bearophile


Thanks for useful feedback.