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

时间:2012-01-03 06:40:57

标签: c++ visual-c++

  

可能重复:
  Returning the address of local or temporary variable
  Can a local variable's memory be accessed outside its scope?

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

以下代码演示了:

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)。这种行为是否对所有编译器都是通用的,以及编译器如何允许我使用指向本地函数变量的指针来访问它指向的值,尽管当函数返回时变量是无效的?

2 个答案:

答案 0 :(得分:3)

你返回一个地址。返回地址有效 - 始终。但在你的情况下,你也取消引用它。这是未定义的行为。从理论上讲,对于未定义的行为,任何事情都可能发生。甚至允许编译器嵌入代码来格式化硬盘。实际上,它将取消引用该地址而不进行任何检查。如果它仍然可访问,它将返回该地址的值,否则将导致访问冲突。

您的地址在堆栈中,因此始终可以访问。根据您之间的调用,值可能仍然存在或不存在。因此,在简单的情况下,您可以获得价值,在更复杂的情况下,您不会。它有时甚至可能有效,有时则不然。

有关更多信息,您应该阅读有关如何在汇编程序中进行函数调用的一些信息,以了解编译器在堆栈上执行的操作(放置参数,返回地址,放置局部变量,返回时清理堆栈,调用约定)

答案 1 :(得分:2)

它可以从堆栈中删除,因为它是本地的,但值将保留,直到另一个覆盖它。 它是c ++不安全的语言,你可以做很多奇怪的事情