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

释放内存时触发堆损坏错误,求排查C++代码问题

问题分析与修复方案

核心问题

你的代码存在两个关键问题,直接导致了堆损坏错误:

  1. 内存分配不足
    你通过calloc(len * 3, 1)分配内存,但每个字节会被格式化为%02X (3个字符,比如"0A "),len个这样的片段总长度是len * 3,但C字符串需要额外1字节存储终止符\0。分配的内存少了这1字节,会导致写入终止符时越界,触发堆损坏检测。

  2. sprintf的未定义行为
    循环内的sprintf(c, "%s%02X ", c, value[i])存在严重问题:sprintf的输入缓冲区(第三个参数的c)和输出缓冲区(第一个参数的c)是同一个,这种情况属于C标准定义的未定义行为,会导致内存写入混乱,甚至直接越界。而且每次调用都会从c的起始位置覆盖之前的内容,最终只会保留最后一次循环的结果,完全达不到拼接十六进制字符串的目的。

修复后的代码

void logHex(char* value, int len, int level)
{
    if (LogHnd)
    {
        // 分配足够内存:每个元素3字符 + 字符串终止符
        char* c = (char*)calloc(len * 3 + 1, 1);
        // 用指针跟踪当前拼接的位置
        char* ptr = c;
        for (int i = 0; i < len; i++)
        {
            // 利用sprintf返回值移动指针,确保内容追加到缓冲区末尾
            ptr += sprintf(ptr, "%02X ", value[i]);
        }
        LogHnd(c, level);
        free(c);
    }
}

修复说明

  • 内存分配修正:增加1字节用于存储字符串终止符,彻底避免越界写入。
  • 消除未定义行为:用ptr指针跟踪缓冲区的当前末尾,每次调用sprintf时从ptr位置写入,同时利用sprintf返回的写入字符数移动指针,确保后续内容追加到正确位置,不会覆盖之前的结果。
  • 如果追求更高安全性(比如防止意外的格式串错误),可以改用snprintf明确限制写入长度:
ptr += snprintf(ptr, (c + len*3 +1) - ptr, "%02X ", value[i]);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 10:50:24