C语言嵌套结构体指针访问数组输出异常值原因排查
异常根因
你代码里的异常是悬空指针访问已回收栈内存导致的未定义行为:
assign_arr函数中定义的int arr[3]是栈上分配的局部变量,生命周期仅在assign_arr函数执行期间有效。函数返回后,这块栈内存就会被系统回收,可被后续的函数调用、栈帧操作任意覆写。你把这个局部数组的地址赋值给X->arr,本质是让结构体持有了一个指向无效内存的野指针,这类访问属于C语言标准定义的未定义行为,程序输出任何值、直接崩溃都是可能的,不存在确定性结果。- 前两次循环能正常输出0、1、2只是巧合:这两段打印逻辑都在
assign_arr返回后、其他函数调用前执行,原先存arr的栈内存还没被新操作覆写,所以暂时能读到之前写入的正确值,这不代表代码逻辑合法。 - 调用
my_func时,程序会为该函数创建新的栈帧,原先存arr[0]的栈位置被my_func的栈数据(参数、局部变量、返回地址等)覆写,所以读到了随机垃圾值32765;剩余两个数组元素所在的内存暂时没被覆盖,所以还能输出1、2,只要后续再有栈操作,这两个值也会变成乱码。
修复方案
你的需求是存储运行时确定长度的动态数组,应该使用堆内存分配实现,不要绑定栈上局部变量:
- 引入标准库头文件
<stdlib.h>,在assign_arr中用malloc申请堆内存存储数组,堆内存生命周期由开发者手动控制,不会随函数返回自动回收。
修复后的assign_arr实现如下:
#include <stdlib.h> void assign_arr(struct arr_wrapper* X, int arr_len){ // arr_len可作为参数运行时传入,适配动态长度需求 int* arr = (int*)malloc(arr_len * sizeof(int)); for (int i = 0; i < arr_len; i++){ arr[i] = i; } X->arr = arr; return; }
- 注意事项:结构体使用完后,必须手动调用
free(arr_wrapper_obj.arr)释放申请的堆内存,避免内存泄漏。 - 不推荐用
static修饰局部数组的方案规避问题:静态数组全局唯一,多次调用assign_arr会覆盖同一块内存,无法适配多实例的动态数组场景。
内容的提问来源于stack exchange,提问作者Marco
相关产品推荐
相关产品推荐

