返回指向本地函数变量的指针

3

可能是重复问题:
返回本地或临时变量的地址
可以访问局部变量的内存吗?

我知道不应该返回指向本地函数变量(本地堆栈变量)的指针,因为当函数返回时,除非我将这些变量设置为静态或在堆上分配它们,否则这些变量将无效并且堆栈将被清除。

以下代码演示了这一点:

const char* v1() {
   return "ABC";
}

const char* v2() {
    string s = "DEF";
    return s.c_str();
}

const char* v3() {
    static string s = "JHI";
    return s.c_str();
}

cout << v1() << endl; // Output: ABC
cout << v2() << endl; // Output: garbage (♀   ╠╠╠╠╠╠╠╠)
cout << v3() << endl; // Output: JHI

然而,我返回了指向原始局部函数变量的指针,并且能够获取它的值,尽管它不是静态的,如下面的代码所示:

int i1() {
    int i = 5;
    return i;
}

int* i2() {
    int i = 6;
    return &i;
}

int* i3() {
    static int i = 7;
    return &i;
}

cout << i1() << endl;  // Output: 5
cout << *i2() << endl; // Output: 6 !!
cout << *i3() << endl; // Output: 7

编译器只是给出了警告,我正在返回本地变量或临时变量的地址(Visual C++ 2008)。这种行为是否适用于所有编译器?编译器如何允许我使用指向局部函数变量的指针来访问它指向的值,尽管该变量在函数返回时被使无效?

3
它的值恰好保留在相同的内存位置。这种方式能够正常工作可能是巧合,也可能是编译时使用了“调试”模式的结果。我不确定问题是什么——你已经知道不应该这样做。请听从编译器发出的警告! - Cody Gray
2个回答

3
你返回了一个地址。返回地址是有效的 - 总是有效的。但在你的情况下,你还对它进行了解引用。这是未定义的行为。理论上,对于未定义的行为,任何事情都可能发生。编译器甚至可以嵌入代码格式化硬盘。实际上,它将在没有任何检查的情况下解引用该地址。如果该地址仍然可访问,则会返回该地址处的值;否则,将导致访问冲突。
你的地址位于堆栈上,因此始终可访问。取决于你之间所做的调用,该值可能仍然存在或不存在。因此,在简单的情况下,你会得到值;在更复杂的情况下,你不会得到值。有时它可能起作用,有时却不起作用。
要获取更多信息,你应该阅读一些有关汇编语言中如何进行函数调用的信息,以了解编译器在堆栈上正在执行的操作(放置参数、返回地址、放置本地变量、返回时的堆栈清除、调用约定)。

2

由于其为局部变量,因此可以从堆栈中删除它,但该值将保留,直到另一个值覆盖它。它是C++这种不安全的语言,可以执行许多奇怪的操作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接