CS50第4周Memory练习题存在内存泄漏问题求助
修复CS50 Memory练习题中的内存泄漏问题
你的代码存在两处关键问题导致内存泄漏,同时还有潜在的越界风险,以下是问题分析和修复方案:
问题分析
- 错误的内存释放操作:循环中你把
malloc得到的地址赋值给plates[idx]后,先将temp设为NULL再执行free(temp)——这相当于释放了空指针,完全没处理之前malloc分配的堆内存。此时plates[idx]仍指向这块内存,但后续没有代码去释放它,程序结束后内存直接泄漏。 - 未清理堆内存:即使去掉循环内的错误释放,程序打印完车牌后也没有释放
plates数组中每个元素指向的堆内存,所有malloc的内存都会被泄漏。 - 潜在数组越界:原代码未限制
idx的上限,如果输入文件的车牌数量超过8个,会超出plates数组的范围,引发未定义行为。
修复后的代码
#include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char *argv[]) { // 检查命令行参数 if (argc != 2) { printf("Usage: ./read infile\n"); return 1; } // 栈上的读取缓冲区 char buffer[7]; // 存储车牌的指针数组 char *plates[8]; FILE *infile = fopen(argv[1], "r"); if(infile == NULL) { return 1; } int idx = 0; // 增加idx<8的判断,防止数组越界 while (fread(buffer, 1, 7 , infile) == 7 && idx < 8) { char *temp = malloc(sizeof(char) * 7); // 处理malloc失败的情况,避免部分内存泄漏 if(temp == NULL) { // 先释放已经分配的内存 for(int i = 0; i < idx; i++) { free(plates[i]); } fclose(infile); return 1; } // 替换换行符为字符串结束符 buffer[6] = '\0'; strcpy(temp, buffer); plates[idx] = temp; idx++; // 这里不需要修改temp或释放,plates[idx-1]还在使用这块内存 } // 打印已读取的车牌(用idx而非固定8,避免打印未初始化元素) for (int i = 0; i < idx; i++) { printf("%s\n", plates[i]); } // 释放所有分配的堆内存,这是解决泄漏的核心步骤 for(int i = 0; i < idx; i++) { free(plates[i]); plates[i] = NULL; // 可选操作,防止后续误操作野指针 } fclose(infile); return 0; }
关键修改点说明
- 移除循环内的错误释放:循环中
plates数组需要持有malloc的内存地址,此时释放会导致plates元素变成野指针,后续打印会出问题。 - 添加堆内存清理步骤:打印完成后遍历
plates数组,逐个释放每个元素指向的堆内存,彻底解决泄漏问题。 - 增加边界判断:在
while循环条件中加入idx < 8,避免数组越界。 - 完善错误处理:
malloc失败时先释放已分配的内存,避免部分泄漏后直接退出。 - 优化打印逻辑:用实际读取的数量
idx作为打印终止条件,避免打印未初始化的数组元素。
内容的提问来源于stack exchange,提问作者Programing Guru
相关产品推荐
相关产品推荐

