1

I'm still new to c++ and have been studying object scope.
I've tested the code below and witnessed some weird behaviors.

struct Test
{
    int value, value2;
    Test() : value(1), value2(10) {};
};


Test* GetTestPointer() {
    Test t;
    t.value = 20;
    return &t;
}

int main() {
    Test* tp = GetTestPointer();
    int a = tp->value;
    int b = tp->value2;
    cout << a << endl;
    cout << b << endl;

    return 0;
}

Output:

20
10

I thought Test t would go out of scope so dereferencing its values in main would either throw an exception or an empty value. Why is it getting valid values as if the object is still alive?

Actually this is what I originally tried:

Test* tp = GetTestPointer();
cout << tp->value << endl;
cout << tp->value2 << endl;

Output:

20
18223279

Here value2 is acting like it's invalid but I can get value just fine.
Conversely I tried reordering them:

Test* tp = GetTestPointer();
cout << tp->value2 << endl;
cout << tp->value << endl;

Output:

10
1459403656

Note that none of this happened when I properly initiated tp with new, as expected.

I know I would never write code like this in real life but I got really curious as to why any of this is happening.

  1. When does t go out of scope in this case?
  2. What does the ordering of cout have anything to do with what tp is dereferencing?
  3. Why when I save them in buffers can I get the correct values?

1 Answers1

2

You just got lucky to be correct value, but in general it is undefined behavior and your compiler should warn you about this.

Try to extend your example to something like this:

int my_sum(int a, int b) {return a + b;}
int main() {
    int res;
    Test* tp = GetTestPointer();
    res = my_sum(1, 2);
    int a = tp->value;
    int b = tp->value2;
    cout << a << endl;
    cout << b << endl;

    return 0;
}

You will see different output because your local scoped Test object was overwritten by another function call.

WHen you use new statement, then your object is not created locally, but on the HEAP memory and therefore it is valid when you go out of function scope. In this case, you have to use delete, to delete this object later.

unalignedmemoryaccess
  • 7,246
  • 2
  • 25
  • 40
  • More like unlucky I guess. I did get a warning that I was returning address of a temporary... but otherwise it compiled and ran just fine without any interruptions. Do undefined behaviors always go unnoticed like this? Dividing by zero for example would terminate my program. – LinguistTroubadour Jul 28 '17 at 10:00
  • You were unlucky because it may fail your program in the future :) But in general, undefined behavior can easily crash your execution :) @LinguistTroubadour – unalignedmemoryaccess Jul 28 '17 at 10:03