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

CS50第四周JPEG恢复C代码出现未知段错误,求技术帮助

修复CS50 JPEG恢复程序的段错误及逻辑问题

你的程序出现段错误和功能异常,核心问题集中在以下几点:

  • 未检查文件打开结果
    打开输入文件后没有判断返回的文件指针是否为NULL,如果文件不存在或无权限访问,后续fread操作会访问空指针,直接触发段错误。添加检查:

    FILE *f = fopen(argv[1], "rb");
    if (f == NULL) {
        printf("无法打开输入文件\n");
        return 1;
    }
    
  • fread参数使用错误
    fread的参数逻辑是(缓冲区, 单个元素大小, 元素数量, 文件指针)。你原来的代码fread(&b, sizeof(b), sizeof(b), f)会尝试读取4个4字节的元素(共16字节),完全偏离了“读取4字节检测JPEG头”的需求,还会导致文件指针跳转过快,引发内存访问问题。正确写法:

    // 每次读取4字节,判断是否成功读取全部4字节
    while (fread(b, 1, sizeof(b), f) == sizeof(b)) {
    

    另外,数组名b本身就是指向首元素的指针,不需要加&。

  • JPEG写入逻辑不完整
    当前代码找到JPEG头后只写入一个512块就关闭文件,但JPEG由连续的512块组成,直到下一个JPEG头或文件结束。而且你还漏掉了把检测到的JPEG头写入文件(因为fread已经把这4字节读出来了)。修复后的写入逻辑:

    filecounter++;
    char filename[10];
    snprintf(filename, sizeof(filename), "%03i.jpg", filecounter);
    
    FILE *img = fopen(filename, "wb");
    if (img == NULL) {
        printf("无法创建图片文件\n");
        fclose(f);
        return 1;
    }
    
    // 先写入刚才检测到的JPEG头
    fwrite(b, 1, sizeof(b), img);
    
    BYTE BLOCK[512];
    size_t bytes_read;
    while (1) {
        bytes_read = fread(BLOCK, 1, sizeof(BLOCK), f);
        if (bytes_read == 0) break; // 文件结束
    
        // 检查当前块是否是新的JPEG头
        if (BLOCK[0] == 0xff && BLOCK[1] == 0xd8 && BLOCK[2] == 0xff && (BLOCK[3] & 0xf0) == 0xe0) {
            // 回退4字节,留给下一次循环检测
            fseek(f, -4, SEEK_CUR);
            break;
        }
    
        fwrite(BLOCK, 1, bytes_read, img);
    }
    fclose(img);
    
  • 使用文本模式操作二进制文件
    Windows系统中,"r"/"w"模式会自动转换换行符,破坏JPEG的二进制结构。必须用"rb"(读二进制)和"wb"(写二进制)模式打开文件。

  • 用snprintf替代sprintf提升安全性
    sprintf存在缓冲区溢出风险,snprintf可以指定写入的最大字节数,避免意外溢出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 08:35:06