malloc内存泄漏警告排查:copyMemZone测试代码问题分析
内存泄漏警告分析与代码问题修正
这个警告的提示位置有点偏差,但核心指出的风险是真实存在的,同时你的代码还有其他潜在问题,下面具体拆解:
一、警告的真实原因
虽然clang-analyzer把警告标在了dataDest的malloc行,但实际问题出在**dataSource的潜在泄漏**:
- 当
dataDest分配失败时,你直接return EXIT_FAILURE,此时dataSource已经完成内存分配,但没有被free,这就触发了分析器的泄漏检测。 - 分析器的提示行错位,是因为它跟踪到泄漏的根源和
dataDest的分配分支有关,所以指向了这行代码,但警告的核心(dataSource可能泄漏)是对的。
二、代码里的其他问题
- 缓冲区溢出风险:
copyMemZone函数完全没检查目标缓冲区的大小是否够装要复制的内容。如果sizeMaxDest小于endMemo - beginMemo,写数据的时候会直接越界,触发未定义行为。 - 类型不匹配:
main里的beginMemo、endMemo是int(有符号),但copyMemZone的参数是size_t(无符号),要是传个负数进去,逻辑直接乱套。 - 冗余强制转换:
copyMemZone((unsigned char*)dataSource,...)里的强制转换完全多余,dataSource本身就是unsigned char*类型。
三、修正后的代码
#include <cstdlib> #include <QDebug> int copyMemZone(unsigned char* zoneSourceFonc, size_t debutSourceFonc, size_t finSourceFonc, unsigned char** zoneDestFonc, size_t destBufferSize); int copyMemZone(unsigned char *zoneSourceFonc, size_t debutSourceFonc, size_t finSourceFonc, unsigned char **zoneDestFonc, size_t destBufferSize) { // 先校验参数合法性 if (!zoneSourceFonc || !zoneDestFonc) return EXIT_FAILURE; if (debutSourceFonc >= finSourceFonc) return EXIT_SUCCESS; size_t copySize = finSourceFonc - debutSourceFonc; // 检查目标缓冲区是否足够 if (copySize > destBufferSize) return EXIT_FAILURE; // 简化复制逻辑 for (size_t i = 0; i < copySize; ++i) { (*zoneDestFonc)[i] = zoneSourceFonc[debutSourceFonc + i]; } return EXIT_SUCCESS; } int main() { const size_t sizeSource = 10; // 统一用size_t处理内存相关的数值 const size_t beginMemo = 2, endMemo = 8; const size_t sizeMaxDest = 10; unsigned char* dataSource = static_cast<unsigned char*>(malloc(sizeSource * sizeof(unsigned char))); if (!dataSource) { return EXIT_FAILURE; } // 初始化数据源 dataSource[0] = '0'; dataSource[1] = 'X'; dataSource[2] = 'M'; dataSource[3] = 'E'; dataSource[4] = 'M'; dataSource[5] = 'O'; dataSource[6] = 'R'; dataSource[7] = 'Y'; dataSource[8] = '8'; dataSource[9] = '7'; unsigned char* dataDest = static_cast<unsigned char*>(malloc(sizeMaxDest * sizeof(unsigned char))); if (!dataDest) { free(dataSource); // 分配失败时先释放已申请的dataSource return EXIT_FAILURE; } const size_t tailleDest = endMemo - beginMemo; if (copyMemZone(dataSource, beginMemo, endMemo, &dataDest, sizeMaxDest) != EXIT_SUCCESS) { qDebug() << "内存区域复制失败"; } // 输出复制结果 for (size_t i = 0; i < tailleDest; ++i) { qDebug() << QChar(dataDest[i]); } // 释放所有内存 free(dataDest); free(dataSource); return EXIT_SUCCESS; }
四、关键修正点
- 修复了
dataSource的泄漏问题:当dataDest分配失败时,先释放dataSource再退出。 - 给
copyMemZone加了目标缓冲区大小参数,彻底避免越界访问。 - 把所有内存相关的变量换成
size_t类型,消除符号不匹配的隐患。 - 增加了参数合法性校验,让代码更健壮。
内容的提问来源于stack exchange,提问作者Juan
相关产品推荐
相关产品推荐

