我编写了以下简单的程序,对 0 到 9 的数字进行求和:
#include <stdio.h>
#include <stdlib.h>
int* allocArray() {
int arr[10];
return arr;
}
int main(void){
int* p;
int summe = 0;
p = allocArray();
for(int i = 0; i != 10; ++i) {
p[i] = i;
}
for(int i = 0; i != 10; ++i) {
summe += p[i];
}
printf("Sum = %d\n", summe);
}
Run Code Online (Sandbox Code Playgroud)
该代码编译并提供预期结果“45”。但是我收到以下警告:“返回与局部变量‘arr’关联的堆栈内存地址”。我究竟做错了什么?
这是未定义的行为,简单明了。它“起作用”的唯一原因是因为对于这个特定的编译器,堆栈还没有被丢弃,但它是靠借来的时间生存的。
函数调用完成后,其生命周期arr立即结束。在那之后,任何指向的指针都arr将失效并且无法使用。1
您的编译器使用堆栈内存来存储局部变量,并且警告表明您正在将地址返回到现已无效的堆栈变量。
解决这个问题的唯一方法是动态分配内存并返回:
int* allocArray() {
int* arr = calloc(10, sizeof(int));
return arr;
}
Run Code Online (Sandbox Code Playgroud)
您现在负责稍后释放该内存。
您还可以使用以下方法static来延长使用寿命arr:
int* allocArray() {
static int arr[10];
return arr;
}
Run Code Online (Sandbox Code Playgroud)
尽管这也不是没有后果,因为现在arr是共享的,而不是每个函数调用所独有的。
1就像 C 中的许多事情一样,您“不能做”的事情(因为它们会导致未定义的行为和/或崩溃)与您“可以做”的事情(因为语法和编译器允许)之间存在显着重叠。通常您有责任了解您编写的任何代码(无论是暗示的还是其他方式)的后果。