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

在check50中遭遇Valgrind内存错误,寻求故障排查方法

JPEG恢复程序Valgrind内存错误排查

核心内存问题分析

  • 文件名缓冲区内存分配严重不足
    你给jpg分配的内存是sizeof(uint8_t)*sizeof(char),仅1字节,但生成的JPEG文件名格式是%03i.jpg(比如000.jpg),需要至少8字节空间(7个可见字符+1个字符串终止符\0)。sprintf写入时会越界覆盖堆内存,这是Valgrind报错的核心原因。
    修复:直接用栈数组char jpg[8];替代malloc(更安全,无需手动管理内存),或者分配足够内存:char *jpg = malloc(8);。

  • 未关闭之前打开的输出文件句柄
    每次找到新JPEG头时,直接重新赋值images = fopen(...),但未关闭之前打开的images文件,会导致文件资源泄漏,Valgrind会检测到未关闭的文件句柄。
    修复:打开新文件前,检查images是否非空,若非空则先执行fclose(images);。

  • 空指针调用fclose的风险
    如果输入文件中没有任何JPEG,images会始终为NULL,程序末尾执行fclose(images);会触发空指针访问错误。
    修复:关闭前先判断if (images != NULL) fclose(images);。

修正后的关键代码片段

int main(int argc, char *argv[])
{
    int jpgs = 0;
    unsigned char jpgbuffer[512];
    FILE *images = NULL;
    char jpg[8]; // 用栈数组替代malloc,规避内存分配错误

    // (此处补充输入文件image的打开逻辑)

    while (fread(jpgbuffer, sizeof(char), sizeof(jpgbuffer), image) == sizeof(jpgbuffer))
    {
        // JPEG头判断逻辑
        if (/* 此处填入JPEG头检测条件 */)
        {
            // 先关闭之前的输出文件
            if (images != NULL)
            {
                fclose(images);
            }
            sprintf(jpg, "%03i.jpg", jpgs);
            images = fopen(jpg, "w");
            jpgs++;
        }

        if (images != NULL)
        {
            fwrite(jpgbuffer, sizeof(char), sizeof(jpgbuffer), images);
        }
    }

    // 关闭最后一个打开的输出文件
    if (images != NULL)
    {
        fclose(images);
    }
    fclose(image);

    return 0;
}

额外说明

  • 使用栈数组存储文件名无需手动调用free,能避免内存分配大小错误、忘记释放内存等问题。
  • 切换输出文件时必须关闭前一个文件,否则不仅会引发Valgrind报错,还可能导致后续写入数据异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 13:54:24