我可以知道为什么下面的代码没有出错,即使函数返回局部变量的地址 [duplicate]

May i know why the below code is not errored out, even though function returning address of a local variable [duplicate]

提问人:roney km 提问时间:5/11/2023 更新时间:5/11/2023 访问量:69

问:

CPP代码:

#include <iostream>
using namespace std;

int* scopeProblem()
{
    int *bret;
    int b=10;
    bret =&b;
    
    return bret;
}

int main()
{
    cout<<*(scopeProblem());
    return 0;
}

输出为 10

我期望它出错为函数中本地创建的变量地址。 函数执行完成后不应存在。

C++ 变量 scope local

评论

5赞 PaulMcKenzie 5/11/2023
我本来以为它会出错——你说的“出错”是什么意思?出现一个大错误框,说你做错了什么?抱歉,C++ 不是这样工作的。你正在做的是未定义的行为,这意味着任何事情都可能发生。
0赞 Jesper Juhl 5/11/2023
en.cppreference.com/w/cpp/language/ub
0赞 PaulMcKenzie 5/11/2023
此外,C++ 是那些无法保证“出错”的语言之一。它不是 Java 或 python 或类似的语言,当你犯错误时,你会让运行时停止并指出错误。当你在C++中犯了这样的错误时,你需要语言的经验来知道你做错了什么——你不能依靠系统来“出错”。您事先知道您正在访问一个超出范围的项目,这是无效的 - 所以不要故意这样做。
1赞 273K 5/11/2023
MSVC 可以警告:。warning C4172: returning address of local variable or temporary: b
0赞 Bob__ 5/11/2023
有一些工具可以帮助您捕获这些类型的错误,例如,请参阅 godbolt.org/z/PPd75sjv5

答:

0赞 RandomBits 5/11/2023 #1

正如评论者所提到的,使用超出范围的局部变量的地址会产生未定义的行为,即任何事情都可能发生,包括程序纯粹偶然地工作。所以,简短的回答是不要那样做。

但是,如果您很好奇,这就是程序如何(至少在我的环境中)仍然设法输出。程序集显示,当指针被取消引用时,它仍然指向函数的堆栈帧,该帧自调用以来未被修改,因此它仍然恰好包含 .10scopeProblem10

考虑到这一点,您可能可以弄清楚为什么会打印出以下代码(至少在我的平台和编译器上)。中间的调用 将导致分配一个新的堆栈帧,该帧将覆盖 调用 中的堆栈帧。2fooscopeProblem

#include <cassert>
#include <iostream>

int* scopeProblem()
{
    int *bret;
    int b=10;
    bret =&b;

    return bret;
}

auto foo() {
    int a = 0, b = 1, c = 2;
    return a + b + c;
}

int main(int argc, const char *argv[]) {
    auto ptr = scopeProblem();
    auto a = foo();
    std::cout << *ptr << std::endl;
    assert(a == 3);
    return 0;
}