Strange pointer aliasing problem

I'm learning about pointers and structs, so I wrote a little demo program. I'm compiling my code with the GNU G++ compiler.

I have a struct that looks like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
    struct Robot{
        string name;
        int arms;
        int lasers;
        int nukes;
        int heart;

        void haveAHeart(){
            nukes=0;
            lasers=0;
            heart=1;
            cout << "\t" << name << ": 'Humans aren't so bad...'\n";
        }

        void killEverything(){
            nukes=0;
            cout << "\t" << name << ": 'Would you like to play a game?' *boom*\n";
        }
        
        void setName(string name){
            this->name = name;
        }
        
        string getName(){
            return name;
        }
    };


And I have some code like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
    //now things are going to get nuts up in here
    Robot * robots[5];
    
    robots[0] = &robbie; //load in robbie's address
    cout << "Loaded " << robots[0]->name << " into the array\n";
    for(int i=1; i<5; i++){ //make generic robots
        Robot r; //despite this, every pointer will point to the same Robot r
        r.setName("Gamma");
        r.arms=2;
        r.lasers=2;
        r.nukes=0;
        r.heart=-1;
        robots[i] = &r;
    }
    
    Robot s; //let's make a unique robot (note that the variable name is different)
    s.setName("Sigma");
    s.arms = 4;
    s.lasers = 17;
    s.nukes = 5;
    s.heart = -2;
    robots[1] = &s; //store it in the list
    
    /*
    Robot b;   //new robot
    Robot * bPtr = &b;   //make a pointer for the new robot
    *(Robot *)bPtr.name = "Bob";   //this does not compile

    bPtr->name = "Bob";   //use this instead
    */
    
    cout << "We made a bunch of generic Robots\n"
         << "Here is a list of all the robots:\n";
    for(int i=0; i<5; i++){
        cout << "\t" << robots[i]->name << " (pointer:" << robots[i] << ")\n"
             << "\t\tarms: " << robots[i]->arms << "\n"
             << "\t\tlasers: " << robots[i]->lasers << "\n"
             << "\t\tnukes: " << robots[i]->nukes << "\n"
             << "\t\theart: " << robots[i]->heart << "\n";
    }

Note: robbie is an existing Robot struct I had.

My problem is, when I print out a list of the names of the robots, I expect Robbie, Sigma, Gamma, Gamma, Gamma. Instead, I'm getting Robbie, Sigma, Sigma, Sigma, Sigma. Here's my output:
Here is a list of all the robots:
	Robbie (pointer:0x7fff5fbff920)
		arms: 2
		lasers: 0
		nukes: 0
		heart: 1
	Sigma (pointer:0x7fff5fbff8e0)
		arms: 4
		lasers: 17
		nukes: 5
		heart: -2
	Sigma (pointer:0x7fff5fbff900)
		arms: 2
		lasers: 2
		nukes: 0
		heart: -1
	Sigma (pointer:0x7fff5fbff900)
		arms: 2
		lasers: 2
		nukes: 0
		heart: -1
	Sigma (pointer:0x7fff5fbff900)
		arms: 2
		lasers: 2
		nukes: 0
		heart: -1


The pointer for the first Sigma is different than all the other ones, which baffles me even more.
Last edited on
Additionally, if I change r.setName("Gamma") to r.setName("sadfjdksalfjlsd") it works just fine:
Here is a list of all the robots:
	Robbie (pointer:0x7fff5fbff920)
		arms: 2
		lasers: 0
		nukes: 0
		heart: 1
	Sigma (pointer:0x7fff5fbff8e0)
		arms: 4
		lasers: 17
		nukes: 5
		heart: -2
	sadfjdksalfjlsd (pointer:0x7fff5fbff900)
		arms: 2
		lasers: 2
		nukes: 0
		heart: -1
	sadfjdksalfjlsd (pointer:0x7fff5fbff900)
		arms: 2
		lasers: 2
		nukes: 0
		heart: -1
	sadfjdksalfjlsd (pointer:0x7fff5fbff900)
		arms: 2
		lasers: 2
		nukes: 0
		heart: -1


I've compiled and run it on both Linux and MacOS and I get the same behavior. It's really weird.
Last edited on
1
2
3
4
5
6
7
8
9
10
11
    Robot * robots[5];
    //...
    for(int i=1; i<5; i++){ //make generic robots
        Robot r; //despite this, every pointer will point to the same Robot r
        r.setName("Gamma");
        r.arms=2;
        r.lasers=2;
        r.nukes=0;
        r.heart=-1;
        robots[i] = &r;
    }

This creates a Robot object r, assigns the address to robots[i], then destroys the r.

You probably need to allocate them from the heap, but as it stands you'll end up with robots[0] not being from the heap, and the other from the heap. Your delete code will need to know this. It's better to allocate all, including Robbie, from the heap.
Thanks for the help. For future reference, I fixed it by changing the for loop to:
1
2
3
4
5
6
7
8
9
10
    for(int i=1; i<5; i++){ //make generic robots
        Robot * r;
        r = new Robot;
        r->setName("Gamma");
        r->arms=2;
        r->lasers=2;
        r->nukes=0;
        r->heart=-1;
        robots[i] = r;
    }


Is this what you were referring to when you said to "allocate them from the heap"? (I did notice that their addresses are now much lower and unique)
Last edited on
Yes.
Thank you very much.
Topic archived. No new replies allowed.