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

CS50 Recover中为何需检查文件指针非空?能否直接写入?

CS50 Recover作业代码疑问解答

你提到的两段代码核心差异在于对JPEG完整数据的写入逻辑,以及空指针安全处理,下面具体解释:

为什么第一段必须检查output_file非空?

1. 满足JPEG的连续块存储要求

在Recover作业的磁盘镜像里,JPEG是被拆成连续的512字节块存储的:一个完整JPEG = 起始标识块 + N个后续数据块,直到下一个JPEG的起始块出现或文件结束。

第一段代码的逻辑是:

  • 检测到JPEG起始块时,打开对应的输出文件
  • 之后每一次循环读取的512字节块,只要当前有打开的输出文件(output_file != NULL),就写入该文件
    这样就能把当前JPEG的所有后续数据块都写入到同一个文件里,保证生成的JPEG是完整可打开的。

而第二段代码只在检测到起始块时写入那一个512字节块,后续属于该JPEG的所有数据块都被忽略了,生成的文件只有开头512字节,是损坏的。

2. 避免空指针操作的安全风险

fopen并非一定能成功(比如磁盘满了、权限不足、路径错误),失败时会返回NULL指针。如果直接对NULL调用fwrite,会触发未定义行为——程序可能崩溃、输出垃圾数据,甚至破坏其他内存数据。

第一段代码的if (output_file != NULL)检查,确保只有文件成功打开时才执行写入,从根源避免了这种风险。而第二段代码完全没有这个检查,一旦fopen失败,后续操作必然出问题。

3. 过滤开头的无效垃圾数据

磁盘镜像的开头可能存在不属于任何JPEG的垃圾数据,第一段代码里output_file初始化为NULL,这些垃圾数据会因为output_file == NULL被跳过,不会写入任何文件,保证输出的都是有效JPEG内容。


第一段完整代码(整理后)

FILE *input_file = fopen(argv[1], "r");
// 检查输入文件是否打开失败
if (input_file == NULL)
{
    printf("Could not open file");
    return 2;
}

// 存储512字节数据块的缓冲区
unsigned char buffer[512];
// 统计找到的JPEG数量
int count_image = 0;
// 输出文件指针,初始化为NULL
FILE *output_file = NULL;

// 分配文件名存储内存(格式为"000.jpg",占8字节)
char *filename = malloc(8 * sizeof(char));

// 循环读取512字节块,直到文件结束
while (fread(buffer, sizeof(char), 512, input_file))
{
    // 检查当前块是否是JPEG起始标识
    if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
    {
        // 生成格式化文件名(如001.jpg)
        sprintf(filename, "%03i.jpg", count_image);
        // 打开输出文件
        output_file = fopen(filename, "w");
        // 计数加一
        count_image++;
    }
    // 如果输出文件已成功打开,写入当前数据块
    if (output_file != NULL)
    {
        fwrite(buffer, sizeof(char), 512, output_file);
    }
}

// 释放内存并关闭文件
free(filename);
fclose(output_file);
fclose(input_file);

return 0;

第二段代码片段

if(buffer[0]==0xff && buffer[1]==0xd8 && buffer[2]==0xff && (buffer[3] & 0xf0) == 0xe0)
{
    sprintf(filename, "%03i.jpg", counter);
    img = fopen(filename, "w");
    fwrite(buffer,sizeof(uint8_t),512,img);
    counter++;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 18:09:24