1

可能重复:
可以在其范围之外访问局部变量的内存吗?

我最近遇到了以下代码:

#include <stdio.h>

int* abc () {
   int a[3] = {1,10,100};
   return a;
}
int* xyz () {
   int b[1] = {222};
   return b;
}
int main() {
   int *a, *b;
   a = abc();
   b = xyz();
   printf("%d\n", *a);
   return 0;
}

输出是222'a'指向在xyz().

我的问题是:

  1. 为什么 a 指向里面声明的数组xyz()

  2. 函数内部声明的数组xyz()应该在函数执行后超出范围。为什么那没有发生?

4

6 回答 6

8

2:它正在发生,整个程序有未定义的行为。这不是一个正确的程序,考虑 if 和 but 没有什么意义。

于 2012-09-17T16:28:35.593 回答
3

您可能会看到222,因为用于本地数组 in 的内存abc已用于其他用途 - 函数的堆栈xyz。你正在传递一个地址到那个内存。再做几个函数调用,*a可能包含一些其他值。

函数执行后应该超出范围。为什么那没有发生?

变量超出范围。在函数外部使用该地址是不正确的代码:使用指向从函数返回的本地数据的指针是未定义的行为。

于 2012-09-17T16:27:15.213 回答
2

变量ab是自动变量;在其他函数中使用它们的地址是一种未定义的行为。任何事情都可能发生:你不能期望输出(例如,优化编译器可以删除一些非法代码)。

于 2012-09-17T16:27:46.733 回答
1

要返回指针,它必须是指向动态分配变量或静态或全局变量的指针。

返回指向堆栈变量的指针将导致您拥有指向堆栈的指针,当您调用新方法时该指针将被重用。

在您的情况下,将堆栈变量重用于另一个数组并覆盖调用第一个方法时存储的旧值。

尝试printf再次调用您将看到不同的输出,因为第一次调用 printf 更改了堆栈内容。

于 2012-09-17T16:34:22.570 回答
0

为什么那没有发生?

它确实发生了,只是形式上的。未定义的行为没有义务崩溃或行为不端——它们“任何事情都可能发生”意味着它也可以看似没有任何错误地运行。我刚刚回答了一个类似的问题。

于 2012-09-17T16:29:00.803 回答
0

函数abcxyz每个都将地址传回给本地创建的数组。随后的调用正在混合先前使用的内存(并传回给您)。

这些被称为自动局部变量。

您需要将这些数组声明为静态或以不同的方式分配内存。

于 2012-09-17T16:29:51.443 回答