开发者

Reference to a temporary variable - why doesn't compiler detect it?

开发者 https://www.devze.com 2023-04-06 06:40 出处:网络
I hope this is not a duplicate, I\'ve read a number of related questions but no one seemed to cover this case:

I hope this is not a duplicate, I've read a number of related questions but no one seemed to cover this case:

 #include <iostream>

int* return_dangling_p()
{
        int x = 1;
        return &x;  // warning: address of local variable 'x' returned
}

void some_func()
{
    int x = 2;
}

int main(int argc, char** argv)
{
    //  UB 1
    int* p = return_dangling_p();
    std::cout << *p;               // 1
    some_func();
    std::cout << *p;               // 2, some_func() wrote over the memory

    // UB 2
    if (true) {
        int x = 3;
        p = &x;     // why does compiler not warn about this?
    }
    std::cout << *p;    // 3
    if (true) {
        int x = 4;    
    }
    std::cout << *p;    // 3, why not 4?

    return 0;
}

I thought these are two cases of the same undefined behaviour. The output is 1233 while I (naively?) expected 1234.

So my question is: why doesn't compiler complain in the second case and why开发者_StackOverflow中文版 the stack isn't rewritten like in the case of 12? Am I missing something?

(MinGW 4.5.2, -Wall -Wextra -pedantic)

EDIT: I'm aware that it's pointless to discuss outputs of UB. My main concern was if there's any deeper reason to why one is detected by the compiler and the other isn't.


I'm not sure why the compiler doesn't complain. I suppose it's not a very common use-case, so the compiler authors didn't think to add a warning for it.

You can't infer anything useful about behaviour you observe when you are invoking undefined behaviour. The final output could have been 3, it could have been 4, or it could have been something else.

[If you want an explanation, I suggest look at the assembler that the compiler produced. If I had to guess, I'd say that the compiler optimised the final if (true) { ... } away entirely.]


why doesn't compiler complain in the second case

I am not sure. I suppose it could.

why the memory isn't rewritten like in the case of 12

It's undefined behaviour. Anything can happen.

Read on if you're really curious...

When I compile your code as-is, my compiler (g++ 4.4.3) places the two x variables in UB 2 at different locations on the stack (I've verified this by looking at the disassembly). Therefore they don't clash, and your code also prints out 1233 here.

However, the moment I take the address of the second x, the compiler suddenly decides to place it at the same address as the first x, so the output changes to 1234.

if (true) {
    int x = 4;    // 3, why not 4?
    &x;
}

Now, this is what happens when I compile without any optimization options. I haven't experimented with optimizations (in your version of the code, there's no reason why int x = 4 can't be optimized away completely).

The wonders of undefined behaviour...

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号