问题描述
我有一个很基本的问题,不知道之前有人问过没有?我试图找到答案,但找不到。
我在不同的 IDE 中使用 C++,例如 Visual Studio 2019、代码块、Dev C++ 和名为OnlineGDB的在线编译器。
我这里有简单的代码。
#include <iostream>
int* getInt(){
int x = 10;
return &x;
}
int main()
{
int *ptr = getInt();
std::cout<<*ptr;
return 0;
}
我们知道 x 在 getInt 中是一个局部变量,当 getInt 函数完成时 x 将被局部作用域的概念销毁。我正在返回 x 的引用并存储在 main 中的指针中。现在按照本书,它不应该打印任何内容或垃圾值,因为 x 已被销毁。
但是当我在不同的 IDE 中运行此代码时,它们会给出不同的结果。让我们看看结果。
在OnlineGDB:
警告:局部变量‘x’的地址返回了[-Wreturn-local-addr]。
它显示这个警告并且不打印任何东西。
在 Dev-C++ 5.7.1 中:
警告:局部变量‘x’的地址返回了[-Wreturn-local-addr]。
它显示此警告但也打印值 10。
在代码块中:
警告:局部变量‘x’的地址返回了[-Wreturn-local-addr]。
在 Visual Studio 2019 中:它不显示任何警告并打印值 10。
那么幕后实际发生了什么,我错过了什么?为什么相同的代码在不同的环境下会有不同的结果。
解决方法
正如其他人所提到的,这只是未定义的行为,编译器在生成指令时可以将其视为任何内容。在您的情况下,您可能很幸运程序没有崩溃。看看同一个程序 here 生成了什么:
mov DWORD PTR [rbp-0x4],0xa
mov eax,0x0
这里的 eax
是用来存储函数返回值的寄存器。它用 0x0
填充它,并在 main()
函数中取消引用它,导致崩溃。检查编译器的反汇编并查看它们生成的指令。应该让您更深入地了解编译器可能发生的情况。但底线:
“不要从函数返回局部变量的地址”
还有,
“检查编译器输出中的警告。”
您很可能会收到警告。