动态数组实现中访问指针触发SIGBUS错误及free报错问题排查
动态数组内存错误问题排查与解决
问题背景
这是一段动态数组的部分实现代码,仅用于测试功能。测试时遇到两个问题:
- 未调用
free释放malloc分配的buf内存时,出现SIGBUS错误,定位到main函数中访问control.buf的操作; - 添加
free语句后,触发报错:pointer being freed was not allocated。
测试代码
#include <stdio.h> #include <stdlib.h> #define MINCAP 100 typedef struct{ void **buf; int size, capacity; } DynArray; void *peek_at_loc(DynArray *dyn, int loc){ if (!dyn || loc < 0 || loc > dyn->size) return NULL; return dyn->buf[loc-1]; } void initialise(DynArray *dyn, int capacity){ if(!dyn || dyn->buf) return; if (capacity <= 0){ dyn->capacity = MINCAP; }else{ dyn->capacity = capacity; } dyn->buf = (void**)malloc(dyn->capacity*sizeof(void*)); } int main() { DynArray control; int a, b; initialise(&control, 5); printf("%p", control.buf); *control.buf = &a; *(control.buf+1) = &b; control.size = 2; int *c = peek_at_loc(&control, 2); printf("%p %p", &b, c); free(control.buf); }
添加free后的错误信息(翻译后)
Dynamic_Arr(27352,0x1da499ec0) malloc: *** 错误:对象0x10062bf30:要释放的指针未被分配 Dynamic_Arr(27352,0x1da499ec0) malloc: *** 在malloc_error_break处设置断点以调试 zsh: 中止 ./Dynamic_Arr
错误原因分析
- 结构体成员未初始化,存在随机垃圾值:
main中声明的DynArray control是栈上的局部变量,未显式初始化buf、size、capacity,这些成员会被赋予栈内存中的随机值。 initialise函数的前置判断失效:函数开头的if(!dyn || dyn->buf) return;逻辑中,dyn->buf的随机值可能非空,导致后续的malloc语句完全没执行,control.buf始终是无效的随机地址。- SIGBUS错误根源:当
control.buf是无效随机地址时,对*control.buf或*(control.buf+1)的写入操作会访问非法内存,触发SIGBUS错误。 free报错原因:若initialise未执行malloc,control.buf的随机地址并非malloc分配的内存块,调用free时就会触发“要释放的指针未被分配”的错误。
解决方案
1. 显式初始化结构体成员
在main中声明结构体时,直接初始化所有成员,确保buf初始为NULL,让initialise的判断逻辑正常工作:
DynArray control = {NULL, 0, 0};
2. 补充malloc失败的错误处理
在initialise函数中,检查malloc的返回值,避免后续操作访问NULL指针:
dyn->buf = (void**)malloc(dyn->capacity*sizeof(void*)); if (dyn->buf == NULL) { fprintf(stderr, "malloc failed\n"); exit(EXIT_FAILURE); }
3. 优化initialise的判断逻辑(可选)
如果不想依赖结构体初始化,可以调整判断逻辑,确保即使buf有随机值,也能正确执行初始化(但显式初始化是更稳妥的方案):
// 去掉对dyn->buf的判断,改为允许重新初始化(根据需求调整) void initialise(DynArray *dyn, int capacity){ if(!dyn) return; // 如果已有分配的内存,可选择先释放再重新分配(根据需求) if (dyn->buf) { free(dyn->buf); } if (capacity <= 0){ dyn->capacity = MINCAP; }else{ dyn->capacity = capacity; } dyn->buf = (void**)malloc(dyn->capacity*sizeof(void*)); if (dyn->buf == NULL) { fprintf(stderr, "malloc failed\n"); exit(EXIT_FAILURE); } dyn->size = 0; // 初始化size为0 }
修改后的完整测试代码
#include <stdio.h> #include <stdlib.h> #define MINCAP 100 typedef struct{ void **buf; int size, capacity; } DynArray; void *peek_at_loc(DynArray *dyn, int loc){ if (!dyn || loc < 1 || loc > dyn->size) return NULL; // 修正loc的下限判断,loc从1开始的话,loc<1更合理 return dyn->buf[loc-1]; } void initialise(DynArray *dyn, int capacity){ if(!dyn) return; if (capacity <= 0){ dyn->capacity = MINCAP; }else{ dyn->capacity = capacity; } dyn->buf = (void**)malloc(dyn->capacity*sizeof(void*)); if (dyn->buf == NULL) { fprintf(stderr, "malloc failed\n"); exit(EXIT_FAILURE); } dyn->size = 0; // 显式初始化size为0 } int main() { DynArray control = {NULL, 0, 0}; // 显式初始化结构体 int a, b; initialise(&control, 5); printf("buf address: %p\n", control.buf); *control.buf = &a; *(control.buf+1) = &b; control.size = 2; int *c = peek_at_loc(&control, 2); printf("&b: %p, c: %p\n", &b, c); free(control.buf); return 0; }
内容的提问来源于stack exchange,提问作者Anonymousstriker38596
相关产品推荐
相关产品推荐

