释放内存时触发堆损坏错误,求排查C++代码问题
问题分析与修复方案
核心问题
你的代码存在两个关键问题,直接导致了堆损坏错误:
内存分配不足
你通过calloc(len * 3, 1)分配内存,但每个字节会被格式化为%02X(3个字符,比如"0A "),len个这样的片段总长度是len * 3,但C字符串需要额外1字节存储终止符\0。分配的内存少了这1字节,会导致写入终止符时越界,触发堆损坏检测。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
相关产品推荐
相关产品推荐

