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

malloc/free出现double free or corruption错误排查求助

解决double free or corruption (!prev)的问题

看起来你遇到的堆内存错误,根源是几个明显的内存操作不当,我来帮你拆解分析:

核心问题1:malloc分配的内存不足,导致堆溢出

你这里的malloc只分配了strlen(a)+strlen(b)字节:

MessageOut = (char*)malloc(strlen(a)+strlen(b));

但当你用sprintf(MessageOut, "%s%s", a, b)拼接字符串时,会写入strlen(a)+strlen(b)个字符,再加上字符串末尾必须的'\0'终止符,总共需要**strlen(a)+strlen(b)+1字节**。内存不足会直接溢出,破坏malloc内部的堆管理结构——第一次循环可能只是轻微破坏,还没触发错误,但几次循环后堆结构彻底混乱,就会触发double free or corruption的报错。

核心问题2:无效的sprintf调用,触发未定义行为

看你初始化a和b的代码:

sprintf(a,"blablabla",strlen(a));
sprintf(b,"blablabla",strlen(b));

格式字符串"blablabla"里没有任何占位符(比如%d),但你却传递了额外的参数strlen(a)/strlen(b)。这种用法属于未定义行为,可能会随机篡改内存数据,进一步加剧堆结构的损坏。而且strlen(a)在a未初始化的情况下调用,会读取栈上的随机数据直到遇到'\0',这也是未定义行为。

核心问题3:指针打印的错误用法

你用printf("%x\n",(uint)MessageOut);打印指针地址,在64位系统上uint是32位类型,会截断64位指针的高位,导致显示的地址不完整。正确的做法是用%p格式符:

printf("%p\n", MessageOut);

修复方案

我把修复后的关键代码片段列出来,你可以参考:

void programm(){
    ... 创建变量并从socket获取信息 ...
    char a[512] = {0}; // 初始化栈数组,避免未定义行为
    char b[512] = {0};
    // 修复sprintf调用:如果是赋值固定字符串,用strcpy更安全
    strcpy(a, "blablabla");
    strcpy(b, "blablabla");
    // 或者如果需要格式化包含长度的字符串,要对应占位符(示例)
    // sprintf(a, "blablabla length: %zu", strlen(a));

    char* MessageOut = NULL;
    size_t total_len = strlen(a) + strlen(b);
    // 分配足够的内存,包括'\0'的空间
    MessageOut = malloc(total_len + 1);
    if(MessageOut == NULL) {
        printf("MessageOut Is Null\n");
        return; // 内存分配失败,直接返回避免后续错误
    }
    printf("%p\n", MessageOut);
    printf("Size of Malloc: %zu\n", total_len + 1);

    // 拼接字符串
    sprintf(MessageOut, "%s%s", a, b);
    // 修改前4个字节
    MessageOut[0] = 0x02;
    MessageOut[1] = Data[1];
    MessageOut[2] = Data[2];
    MessageOut[3] = 0x03;

    // sendto的长度是实际要发送的字节数,这里是total_len(因为修改的是内容,长度不变)
    ssize_t byte_nb = sendto(client_socket, MessageOut, total_len, 0, 
                           (struct sockaddr *)&dist_addr, addr_len);
    if (byte_nb == -1) {
        printf("send error: %s\n", strerror(errno));
    } else {
        printf("%zd bytes sent\n", byte_nb);
    }

    printf("%s\n", MessageOut);
    printf("%p\n", MessageOut);
    free(MessageOut);
    MessageOut = NULL; // 置空防止野指针
    printf("Test\n");
}

额外说明

为什么第一次循环正常,几次后才报错?因为堆内存的损坏是渐进式的:第一次溢出可能只是破坏了堆的管理元数据,但glibc的内存检查机制还没检测到;后续几次malloc/free操作不断读写损坏的堆结构,最终触发了内存错误提示。

内容的提问来源于stack exchange,提问作者Thierry

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:19:10