CS50 2023 Pset4 Recover程序内存错误排查求助
CS50 2023第4周Recover习题集内存错误排查
你的代码存在两个核心问题,直接导致了内存错误:
1. 未关闭已打开的输出文件,引发资源泄漏
当检测到新的JPEG文件头时,程序直接调用fopen打开新的输出文件,但之前已经打开的输出文件没有被关闭。操作系统对进程可打开的文件句柄数量有限制,这种重复打开不关闭的行为会造成资源泄漏,触发内存错误。
2. 可能对空指针执行fclose操作
如果输入文件中没有任何JPEG数据,outputFile会一直保持NULL状态。程序最后执行fclose(outputFile)时,相当于尝试关闭一个空指针,这属于未定义行为,必然引发内存错误。
修正后的代码
#include <stdio.h> #include <stdlib.h> #include <stdint.h> typedef uint8_t BYTE; int main(int argc, char *argv[]) { if (argc != 2) { printf("Wrong usage\n"); return 1; } FILE *inputFile = fopen(argv[1], "r"); if (inputFile == NULL) { printf("File cannot be opened\n"); return 1; } BYTE buffer[512]; int counter = 0; FILE *outputFile = NULL; char filename[8]; size_t bytesRead; while ((bytesRead = fread(buffer, sizeof(BYTE), 512, inputFile)) != 0) { if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0) { // 打开新文件前,先关闭之前的输出文件(如果存在) if (outputFile != NULL) { fclose(outputFile); } sprintf(filename, "%03i.jpg", counter); outputFile = fopen(filename, "w"); counter++; } if (outputFile != NULL) { // 写入实际读取到的字节数,避免最后一次写入越界 fwrite(buffer, sizeof(BYTE), bytesRead, outputFile); } } // 关闭最后一个输出文件(仅当它被打开过) if (outputFile != NULL) { fclose(outputFile); } fclose(inputFile); return 0; }
关键修改说明
- 每次打开新输出文件前,先检查并关闭之前的输出文件,避免资源泄漏
- 关闭输出文件前增加非空判断,防止对空指针执行关闭操作
- 记录每次
fread实际读取的字节数,用该数值执行fwrite,确保最后一次写入的是实际读取到的数据,避免缓冲区越界
内容的提问来源于stack exchange,提问作者Berra Eylül Toprak
相关产品推荐
相关产品推荐

