You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

动态数组实现中访问指针触发SIGBUS错误及free报错问题排查

动态数组内存错误问题排查与解决

问题背景

这是一段动态数组的部分实现代码,仅用于测试功能。测试时遇到两个问题:

  1. 未调用free释放malloc分配的buf内存时,出现SIGBUS错误,定位到main函数中访问control.buf的操作;
  2. 添加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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 13:18:17