为什么VisualStudio和DEV-C++不破坏本地变量,而其他IDE则是:C++

为什么VisualStudio和DEV-C++不破坏本地变量,而其他IDE则是:C++,c++,c++11,visual-c++,c++14,c++17,C++,C++11,Visual C++,C++14,C++17,我有一个非常基本的问题,我不知道以前有没有人问过?我试图找到答案,但没有找到 < >我使用C++ C++,使用Visual Studio 2019、代码块、DEV C++和在线编译器OnlineGDB等。 我这里有简单的代码 #include <iostream> int* getInt(){ int x = 10; return &x; } int main() { int *ptr = getInt(); std::cout<&l

我有一个非常基本的问题,我不知道以前有没有人问过?我试图找到答案,但没有找到

< >我使用C++ 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


那么引擎盖下到底发生了什么,我错过了什么?为什么相同的代码在不同的环境中有不同的结果。

正如其他人所提到的,这只是未定义的行为,编译器在生成指令时可以将其视为任何东西。在你的情况下,你可能只是幸运的程序没有崩溃。看看同一个程序生成了什么:

 mov    DWORD PTR [rbp-0x4],0xa
 mov    eax,0x0
这里eax是用于存储函数返回值的寄存器。它用0x0填充它,在主函数中取消引用时,会导致崩溃。检查编译器的反汇编并查看它们生成的指令。应该让您对编译器可能发生的情况有更多的了解。但是巴托洛林:

不从函数返回局部变量的地址

而且

检查编译器输出中的警告


您很可能会收到警告。

未定义的行为就是未定义的行为。x走了,ptr悬着。取消引用ptr是未定义的行为,无需诊断。轻松阅读将您在Visual Studio上的警告级别提高到级别4,然后看看会发生什么。谢谢@RichardCritten。如果它是未定义的行为,那么为什么它总是打印我在x中设置的值。未定义行为打印一个,两次,但不是每次,不是吗?不要假设UB与random相同。。对于未定义的行为,您所能做的就是删除它。根据定义,UB是不可能推理的,没有因果链。在接下来的1000000年里,它可能会表现出相同的行为,然后引起《时间旅行》关于未定义行为的另一篇好文章:尝试添加-O3,看看你能做些什么get@RichardCritten我已经看到了,因为这是我的默认级别:。它完全删除了对函数的调用,只是一个xor eax,eax即0,主要是它只添加了一个ud2,甚至没有调用getInt。我试图说明的一点是,编译器可以自由选择如何在UB条件下运行,并引用了一个示例来说明我的观点。