C语言全局指针数组在自定义函数与main函数中取值不一致问题
问题原因
出现打印值不一致是典型的野指针访问问题:
save_value函数内定义的int vet[64]是栈上分配的局部数组,生命周期仅和save_value函数的执行周期绑定- 函数运行过程中,
vet占用的栈内存还处于合法可用状态,所以函数内通过temp里存的地址能读到正确赋值 - 一旦
save_value执行完毕返回main,该函数对应的栈帧会被系统回收,vet的内存空间会被标记为可复用,之前存在temp里的所有vet元素地址全变成无效地址 - 此时在
main里解引用这些地址,读到的是栈空间被覆写后的随机值,属于C语言标准里定义的未定义行为,结果不可预期 - 额外提个细节问题:全局数组
temp定义长度为65,实际只用到前64个元素,属于冗余定义,虽然不触发报错,但建议和实际使用长度对齐。
修复方案
以下两种修改方式都可以解决问题,按需选择即可:
方案1:将存储值的数组也定义为全局变量
全局变量分配在进程全局数据段,生命周期贯穿程序整个运行周期,不会随函数返回被回收,指针指向的内存全程有效:
int *temp[64]; int vet[64]; // 将原函数内的局部数组挪到全局作用域 static void save_value(int t){ int sum; int i; for(i=0;i<64;i++){ vet[i]=0; temp[i]=0; } for(i=0; i<64; i++){ sum = t ++; vet[i]=sum; temp[i]=&vet[i]; printf("Temp for = %d\n", *temp[i]); } printf("\n"); } int main(int argc, char** argv) { int i; int value; value=1; save_value(value); for(i=0; i<64; i++){ printf("Temp = %d\n", *temp[i]); } return 0; }
方案2:使用动态申请的堆内存存储值
堆内存生命周期由程序员手动管理,不会随函数返回自动释放,注意使用完后要手动释放避免内存泄漏:
#include <stdlib.h> // 引入内存申请函数的头文件 int *temp[64]; static void save_value(int t){ int sum; int i; for(i=0;i<64;i++){ temp[i] = malloc(sizeof(int)); // 为每个指针申请独立的堆内存空间 } for(i=0; i<64; i++){ sum = t ++; *temp[i] = sum; // 直接将值写入申请好的堆内存 printf("Temp for = %d\n", *temp[i]); } printf("\n"); } int main(int argc, char** argv) { int i; int value; value=1; save_value(value); for(i=0; i<64; i++){ printf("Temp = %d\n", *temp[i]); free(temp[i]); // 使用完成后释放堆内存 } return 0; }
注意事项
C语言中所有在函数/代码块内部定义的非静态局部变量,都分配在栈空间上,代码块执行结束后内存就会被自动回收。绝对不要把这类局部变量的地址传出代码块外部使用,否则轻则出现值错乱,重则直接触发段错误导致程序崩溃。
内容的提问来源于stack exchange,提问作者Frencydark
相关产品推荐
相关产品推荐

