已正确初始化字符串仍遇段错误?CS50 Recover代码求助
问题排查与修复
段错误的核心原因
你的代码在最后执行fclose(img)时,img大概率还是初始的NULL指针,调用fclose(NULL)属于未定义行为,直接触发段错误。根源是第一个JPEG文件(counter=0)的处理逻辑完全缺失:
- 检测到第一个JPEG头时,
counter != 0为假,既不会打开输出文件,也不会写入数据,counter始终保持0 - 后续即使有更多JPEG头,
counter仍为0,无法进入文件操作分支,img一直是NULL - 循环结束后执行
fclose(img),本质是关闭空指针,直接引发段错误
代码修复要点
- 处理第一个JPEG文件:移除打开文件和写入时的
counter != 0判断,所有检测到JPEG头的情况都要打开对应文件并写入当前块 - 持续写入后续数据块:在非JPEG头的逻辑分支里,若当前已有打开的
img文件,要将读取到的块写入该文件(否则只会保存每个JPEG的第一个块,丢失后续数据) - 避免空指针关闭:最后关闭
img前先判断是否为NULL,仅非空时执行关闭操作
修复后的代码
#include <stdio.h> #include <stdlib.h> #include <stdint.h> int main(int argc, char *argv[]) { // 检查命令行参数数量 if (argc != 2) { printf("Usage: ./recover FILE\n"); return 1; } // 打开存储卡文件 FILE *card = fopen(argv[1], "r"); if (card == NULL) { printf("File could not be opened\n"); return 2; } uint8_t buffer[512]; int counter = 0; FILE *img = NULL; char filename[8] = {0}; // 循环读取每个512字节块 while (fread(buffer, 512, 1, card) == 1) { // 检测JPEG文件头 if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0) { // 若已有打开的文件,先关闭 if (img != NULL) { fclose(img); } // 生成文件名 sprintf(filename, "%03d.jpg", counter); // 打开新的输出文件 img = fopen(filename, "w"); // 写入当前块 fwrite(buffer, 512, 1, img); // 计数器递增 counter++; } // 若当前已有打开的JPEG文件,写入后续块 else if (img != NULL) { fwrite(buffer, 512, 1, img); } } // 关闭剩余打开的文件 fclose(card); if (img != NULL) { fclose(img); } return 0; }
额外说明
filename[8]长度足够:%03d.jpg格式生成的字符串最长为7个字符(如000.jpg),加上字符串结束符\0,8个字节刚好满足需求- 每次打开新文件前关闭旧文件,避免资源泄漏
- 对非JPEG头的块,只要当前有打开的文件就写入,保证每个JPEG文件的完整性
内容的提问来源于stack exchange,提问作者Aniruddha Shirodkar
相关产品推荐
相关产品推荐

