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

CS50 Recover作业:if条件未执行引发Segmentation Fault求助

CS50 Recover作业:段错误与JPEG判断失效修复

导致段错误的直接原因

你的代码在进入else分支时,直接调用fwrite写入img指针,但程序启动后img初始值为NULL——只有当第一个读取的块是JPEG起始块时,img才会被赋值为有效的文件指针。如果第一个块不是JPEG开头,程序就会对空指针执行写操作,直接触发Segmentation Fault。

修复:
在else分支里加个判断,只有img不为空时才执行写入:

else
{
    printf("else executed\n");
    if (img != NULL)
    {
        fwrite(buffer, BLOCK_SIZE, 1, img);
    }
}

JPEG判断条件从未触发的原因

你用fopen(argv[1], "r")打开card.raw,这是文本模式,在Windows等系统下会自动转换换行符,破坏二进制数据的完整性,导致JPEG的起始标记(0xff 0xd8 0xff 0xeX)无法被正确识别。即使在Linux系统下,文本模式也可能带来潜在问题,处理二进制文件必须用二进制模式。

修复:
打开文件时改用二进制模式:

FILE *card = fopen(argv[1], "rb");

同时,创建JPEG文件时也用二进制模式写入:

img = fopen(filename, "wb");

其他优化与防错点

  1. 合并重复代码:你在this_first_jpeg的两个分支里写了几乎一样的文件创建和写入逻辑,可以合并简化:
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] >= 0xe0 && buffer[3] <= 0xef))
{
    printf("if executed\n");
    if (!this_first_jpeg)
    {
        fclose(img);
    }
    sprintf(filename, "%03i.jpg", number_file++);
    img = fopen(filename, "wb");
    fwrite(buffer, BLOCK_SIZE, 1, img);
    this_first_jpeg = false;
}
  1. 检查文件创建是否成功:当前代码没有判断fopen创建JPEG文件是否成功,建议增加判断避免后续出错:
img = fopen(filename, "wb");
if (img == NULL)
{
    printf("Could not create image file.\n");
    fclose(card);
    return 1;
}
  1. 避免空指针关闭:循环结束后,如果没有找到任何JPEG,img还是NULL,直接fclose(img)会出错,加个判断:
if (img != NULL)
{
    fclose(img);
}

修复后的完整代码

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>

#define BLOCK_SIZE 512
typedef uint8_t BYTE;

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        printf("Usage: ./recover FILE\n");
        return 1;
    }

    FILE *card = fopen(argv[1], "rb");
    if (card == NULL)
    {
        printf("Could not open file.\n");
        return 1;
    }

    BYTE buffer[BLOCK_SIZE];
    int number_file = 0;
    char filename[8];
    FILE *img = NULL;
    bool this_first_jpeg = true;

    while(fread(buffer, BLOCK_SIZE, 1, card) == 1)
    {
        printf("while executed\n");
        if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] >= 0xe0 && buffer[3] <= 0xef))
        {
            printf("if executed\n");
            if (!this_first_jpeg)
            {
                fclose(img);
            }
            sprintf(filename, "%03i.jpg", number_file++);
            img = fopen(filename, "wb");
            if (img == NULL)
            {
                printf("Could not create image file.\n");
                fclose(card);
                return 1;
            }
            fwrite(buffer, BLOCK_SIZE, 1, img);
            this_first_jpeg = false;
        }
        else
        {
            printf("else executed\n");
            if (img != NULL)
            {
                fwrite(buffer, BLOCK_SIZE, 1, img);
            }
        }
    }

    fclose(card);
    if (img != NULL)
    {
        fclose(img);
    }

    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 05:24:51