我正在用 C 语言编写堆栈来向朋友演示一些东西。我知道下面的函数返回指向垃圾内存的指针,因此我们不能依赖它们。这就是演示的重点。
#include <stdio.h>
int *oneToTen();
int *elevenToTwenty();
int main() {
int *arr = oneToTen();
for (int i = 0; i < 10; ++i) {
printf("%d\n", arr[i]);
}
elevenToTwenty();
printf("\n\n\n");
for (int i = 0; i < 10; ++i) {
printf("%d\n", arr[i]);
}
return 0;
}
int *oneToTen() {
int arr[10];
for (int i = 0; i < 10; ++i) {
arr[i] = i + 1;
}
return arr;
}
int *elevenToTwenty() {
int arr[10];
for (int i = 0; i < 10; ++i) {
arr[i] = i + 11;
}
return arr;
}
输出基本符合预期。我们得到垃圾内存,调用第二个函数会更改第一个函数返回的内存。
1
1
47405968
1
1833808032
1
-2092245084
-1687584767
9
10
43154832
1
47405968
1
1833808032
1
-2092245084
-1687584767
19
20
但是奇怪的事情发生了。每次我运行这个函数时,这个数组的最后两个元素永远不会被垃圾处理掉。所有其他数组元素都会变成垃圾,但最后两个元素不会。这是为什么?
我不太熟悉内存从堆栈中弹出后会发生什么,所以我真的不知道如何回答这个问题。我的猜测是,这可能与有 8 个值有关,所以它可能是 2 的幂?
编辑:我尝试更改数组中的元素数量,但最后两个元素始终保持不变
如果您在启用警告的情况下编译它,例如在 gcc 中,您将看到:
a.c: In function ‘oneToTen’:
a.c:31:10: warning: function returns address of local variable [-Wreturn-local-addr]
31 | return arr;
a.c: In function ‘elevenToTwenty’:
a.c:41:10: warning: function returns address of local variable [-Wreturn-local-addr]
41 | return arr;
| ^~~
从警告中,你就能找到问题所在。函数中的局部变量是自动变量,在函数退出时将被销毁。 使用指针和动态分配可以解决问题:
#include <stdio.h>
#include <stdlib.h>
#define SIZE 10
int *oneToTen() {
int *arr = malloc(SIZE * sizeof (int));
for (int i = 0; i < SIZE; ++i)
arr[i] = i + 1;
return arr;
}
int *elevenToTwenty() {
int *arr = malloc(SIZE * sizeof (int));
for (int i = 0; i < 10; ++i)
arr[i] = i + 11;
return arr;
}
int main() {
int *arr = oneToTen();
for (int i = 0; i < 10; ++i)
printf("%d\n", arr[i]);
free(arr);
printf("\n\n\n");
arr = elevenToTwenty();
for (int i = 0; i < 10; ++i)
printf("%d\n", arr[i]);
free(arr);
return 0;
}