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

CS50 pset4 recover程序运行触发Segmentation fault问题求助

问题原因分析

以下是导致段错误的核心问题:

  • fread返回值判断逻辑写反

fread返回值为成功读取的元素个数,你代码中写while(fread(buffer, sizeof(BLOCK_SIZE), 1, infile) == 0)意味着只要成功读取到512字节块就直接退出循环,逻辑完全错误。正确写法为判断返回值等于1,代表成功读取一个完整块。

  • 非法访问未初始化的outfile指针

未找到第一个JPEG头时,outfile还未通过fopen赋值,此时走到else分支会直接调用fwrite写野指针;如果输入文件中没有JPEG,循环结束后直接调用fclose(outfile)也会访问野指针,这是触发段错误的直接原因,和valgrind输出的未初始化值访问报错完全对应。

  • 文件打开模式错误

读写二进制文件需要使用"rb"(读二进制)、"wb"(写二进制)模式,你当前用的文本模式"r"/"w"在部分系统下会导致二进制数据解析异常。

  • 文件名数组长度卡边界(非崩溃直接原因,建议优化)

你定义的char file[8]刚好能存下000.jpg加末尾的字符串结束符\0,没有冗余空间,建议直接定义为char file[16]避免后续修改规则时出现缓冲区溢出。

修复后的完整代码
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

int main(int argc, char *argv[])
{
    const int BLOCK_SIZE = 512;
    typedef uint8_t BYTE;

    if (argc != 2)
    {
        printf("Usage: ./recover image\n");
        return 1;
    }

    // 二进制模式打开输入文件
    FILE *infile = fopen(argv[1], "rb");
    if (infile == NULL)
    {
        printf("Could not open input file\n");
        return 2;
    }

    int index = 0;
    FILE *outfile = NULL; // 初始化空指针,避免野访问
    char file[16]; // 扩大文件名数组容量
    BYTE buffer[BLOCK_SIZE];

    // 正确判断fread返回值,成功读一个块才进入循环
    while (fread(buffer, BLOCK_SIZE, 1, infile) == 1)
    {
        // 检测JPEG头
        if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
        {
            // 已经有打开的输出文件,先关闭
            if (outfile != NULL)
            {
                fclose(outfile);
            }
            // 生成新文件名
            sprintf(file, "%03i.jpg", index);
            // 二进制模式打开输出文件
            outfile = fopen(file, "wb");
            if (outfile == NULL)
            {
                printf("Could not create output file %s\n", file);
                fclose(infile);
                return 3;
            }
            index++;
        }
        // 只有输出文件已经打开时才写数据
        if (outfile != NULL)
        {
            fwrite(buffer, BLOCK_SIZE, 1, outfile);
        }
    }

    // 关闭前先判断指针不为空
    if (outfile != NULL)
    {
        fclose(outfile);
    }
    fclose(infile);

    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 01:57:03