0

Cpp Code:

#include <iostream>
using namespace std;

int* scopeProblem()
{
    int *bret;
    int b=10;
    bret =&b;
    
    return bret;
}

int main()
{
    cout<<*(scopeProblem());
    return 0;
}

Output is 10

I was expecting it to error out as variable address created locally in a function. should not exist after function execution is completed.

  • 5
    *I was expecting it to error out* -- What do you mean by "error out"? A big error box show up saying you did something wrong? Sorry, but C++ does not work that way. What you are doing is *undefined behavior*, meaning anything can happen. – PaulMcKenzie May 11 '23 at 00:54
  • https://en.cppreference.com/w/cpp/language/ub – Jesper Juhl May 11 '23 at 01:01
  • Also C++ is one of those languages where there is no *guaranteed* way to "error it out". It is not Java or python or similar language, where when you make a mistake, you have the runtime stop and point out the error. When you make a mistake like this in C++, you need the experience in the language to know you did something wrong -- you cannot rely on the system to "error out". You knew up front you were accessing an item that is out-of-scope which was invalid -- so just don't do it on purpose. – PaulMcKenzie May 11 '23 at 01:05
  • 1
    MSVC can warn: `warning C4172: returning address of local variable or temporary: b`. – 273K May 11 '23 at 01:06
  • There are tools that may help you catching those types of errors, see e.g. https://godbolt.org/z/PPd75sjv5 . – Bob__ May 11 '23 at 01:20
  • Any feedback on my answer? Did you find it useful? – RandomBits May 18 '23 at 01:40

1 Answers1

0

As the commenters mentioned, using the address of a local variable that has gone out of scope produces undefined behavior, i.e. anything may happen including the program working by pure chance. So, the short answer is don't do that.

If you are curious, though, this is how (at least in my environment), the program still manages to output 10. The assembly shows that when the pointer is dereferenced, it is still pointing into what was the stack frame of the scopeProblem function, which is unmodified since the call, so it still happens to contain 10.

With that in mind, you can probably figure out why the following code prints out 2 (at least on my platform and compiler). The intervening call to foo causes a new stack frame to be allocated which overwrites the stack frame from the call to scopeProblem.

#include <cassert>
#include <iostream>

int* scopeProblem()
{
    int *bret;
    int b=10;
    bret =&b;

    return bret;
}

auto foo() {
    int a = 0, b = 1, c = 2;
    return a + b + c;
}

int main(int argc, const char *argv[]) {
    auto ptr = scopeProblem();
    auto a = foo();
    std::cout << *ptr << std::endl;
    assert(a == 3);
    return 0;
}
RandomBits
  • 4,194
  • 1
  • 17
  • 30