0
#include <iostream>
using namespace std;
int * ref () {

 int tmp = 100;
 return &tmp;
}

int main () {

 int * a = ref();
 cout << *a << endl;
}

I know the function ref () is allocated stack space. It will get destroyed as soon as the function exits. So the complier will give warning information. But my question is why the returning result is still correct ?

Fady Hany
  • 77
  • 6
  • 1
    Undefined Behaviour does not need to be incorrect result ... or crash, or nasal demons. The expected result can be (and often is) a result of UB. – pmg Jul 31 '21 at 17:26
  • 1
    Undefined behavior like dereferencing a pointer to an object whose lifetime has expired means _any_ program output is valid, including "the behavior you would have expected if this program had been correct in the first place". – Nathan Pierson Jul 31 '21 at 17:27
  • 1
    At some random point, on someone else's computer, this code will fail. It may not be today, it may be two years down the road, but it will happen. Listen to the compiler warnings; I promise the compiler knows more about C++ than either you or I. – Silvio Mayolo Jul 31 '21 at 17:28
  • Even if it is clearly UB, anyway, there's a precise reason that makes it work and it is explainable. – Roberto Caboni Jul 31 '21 at 17:33
  • Generally: The stack is a funny thing. It does not get allocated/deallocated as necessary. Generally you get some space (~`10kb` on modern linux I think?) so when ref returns, it's stack frame is still there. The program doesn't clear that memory, but just leaves it, so the value is still there. As others pointed out however this is UB, and you are playing russian roulette, and eventually this will fail. – Lala5th Jul 31 '21 at 17:33
  • The question got closed as I was writing my answer. Here's the short summary. Insert another function call of moderate significance between the invocation of `ref` and the invocation of `cout << *a`. The result will be that the invocation of another function will more likely change the stack memory that `a` references. And hence, the program will print something other than `100`. – selbie Jul 31 '21 at 17:35
  • I was going to write an answer, but the question has been closed. This program returns the correct result, for a specific reason and probably will never change.. **as long as the program will stay unchanged**. That's because it is in the lucky situation where the data contained in the pointer illegally returned **is never overwritten**. Because: 1) no functions are called between `ref ()` and `cout` (their local variables would have overwritten `tmp`) - *[continues...]* – Roberto Caboni Jul 31 '21 at 17:45
  • @selbie - What, you mean like [this answer](https://stackoverflow.com/a/6478323/817643)? Rather than answering obvious duplicates, it's better to lead folks to the canonicals. – StoryTeller - Unslander Monica Jul 31 '21 at 17:45
  • *[continues from previous comment...]* 2) the contents of the pointer is passed to `cout` by value, so the local variable is overwritten by `cout` itself, but when a copy of `*a` has already been done, so the value is safe. – Roberto Caboni Jul 31 '21 at 17:46
  • Example of what @selbie meant [here](https://godbolt.org/z/4Txdnbs69). Note that `calculateValue` has no visible effect, so from the compiler's perspective it's free to optimize it out entirely. Just setting the optimization level to three different values in clang produces three different results! – Nathan Pierson Jul 31 '21 at 17:46
  • @pmg, Please help me with this question. If the OP modifies his ref() function to return an int as follow : " int ref( ) { int tmp = 9; return tmp}, and modifies the main() function so that main() expects to get an int and NOT int* from ref(), then will the code be valid and have a well-defined behavior ? -- I guess the answer is YES. – Job_September_2020 Jul 31 '21 at 17:48
  • @Job_September_2020 The code won't be valid because then `int * a = ref();` will fail to compile since `ref` returns an `int` not an `int*`. You'd have to make more changes, and depending on what those changes actually are you would probably get something with well-defined behavior. – Nathan Pierson Jul 31 '21 at 17:49
  • @NathanPierson, I meant to say "the main() function expects to get an int from ref()" in this case. Is it valid then ? – Job_September_2020 Jul 31 '21 at 17:50
  • @Job_September_2020 Yes, I think pretty obviously. At that point you just have a function returning a value and it shouldn't be very surprising that it's well-defined behavior. – Nathan Pierson Jul 31 '21 at 17:54

0 Answers0