微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么 Visual Studio 和 Dev-C++ 不会破坏局部变量而其他 IDE 会:C++

如何解决为什么 Visual Studio 和 Dev-C++ 不会破坏局部变量而其他 IDE 会:C++

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

我在不同的 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() 函数中取消引用它,导致崩溃。检查编译器的反汇编并查看它们生成的指令。应该让您更深入地了解编译器可能发生的情况。但底线:

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

还有,

“检查编译器输出中的警告。”

您很可能会收到警告。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。