文件读取函数崩溃排查:读取多行至结构体时程序异常
帮你排查程序崩溃的几个关键问题
嘿,我看了你的代码,发现好几个直接导致程序崩溃的核心问题,咱们一个个拆解清楚:
1. 野指针写入触发内存错误
你在loadfromfile里定义了char* string[40];,这是一个指针数组,但每个指针都没有指向有效的可写内存空间。直接用strcpy(string[i], line)往这些未初始化的指针里写数据,相当于往随机的内存地址写入,必然触发程序崩溃。
修复方法:
要么给每个指针分配足够的内存:
char* string[40]; // 在strcpy前先分配内存,+1是给字符串结束符'\0'留位置 string[i] = malloc(strlen(line) + 1); if (string[i] == NULL) { perror("malloc failed"); fclose(f); return NULL; } strcpy(string[i], line);
或者直接用二维数组(更简单,适合固定长度的场景):
char string[40][100]; // 最多存40行,每行100字符
2. 循环中重复的i++导致逻辑混乱+数组越界
看你这两段循环:
for(i = 0; i<SIZE*2; i++){ strcpy(hashtbl[i].subscript, string[i]); i++; // 这里多了一个i++! } for(i = 1; i<SIZE*2; i++){ strcpy(hashtbl[i].value, string[i]); i++; // 又多了一个! }
- 每次循环
i会增加2,导致你跳过了一半的元素,逻辑完全错误; - 更严重的是,你的
init_hashtbl只分配了SIZE个Hashtbl元素,但循环条件是i<SIZE*2,这会访问超出分配范围的内存,触发数组越界崩溃。
如果你的逻辑是文件里的行成对出现(奇数行是subscript,偶数行是value),正确的循环应该是这样:
for(i = 0; i < SIZE; i++){ if (string[2*i] != NULL) { strcpy(hashtbl[i].subscript, string[2*i]); } if (string[2*i+1] != NULL) { strcpy(hashtbl[i].value, string[2*i+1]); } }
3. 字符串常量不可修改,写入触发权限错误
在init_hashtbl里,你给subscript和value赋值了字符串常量:
hashtbl[i].subscript = "ZERO"; hashtbl[i].value = "ZERO";
字符串常量是存储在只读内存区的,后面用strcpy往里面写数据会触发内存访问权限错误,直接崩溃。
修复方法:初始化时给指针分配可写的内存:
Hashtbl* init_hashtbl(){ Hashtbl* hashtbl = calloc(SIZE, sizeof(Hashtbl)); if (hashtbl == NULL) { perror("calloc failed"); return NULL; } for(int i = 0; i<SIZE; i++){ // 分配足够的内存(和line的长度匹配,比如100字节) hashtbl[i].subscript = malloc(100); hashtbl[i].value = malloc(100); if (hashtbl[i].subscript == NULL || hashtbl[i].value == NULL) { perror("malloc failed"); // 释放已分配的内存,避免泄漏 for(int j = 0; j < i; j++){ free(hashtbl[j].subscript); free(hashtbl[j].value); } free(hashtbl); return NULL; } strcpy(hashtbl[i].subscript, "ZERO"); strcpy(hashtbl[i].value, "ZERO"); } return hashtbl; }
4. 文件打开失败后未终止函数,导致空指针操作
当fopen(path, "r")返回NULL时,你只打印了FILE NO FOUND!,但没有终止函数,程序会继续执行后面的while(fgets(...))和fclose(f),这时候f是NULL,调用fclose(NULL)会直接崩溃。
修复方法:在打印错误后立即返回:
if(f == NULL){ printf("FILE NO FOUND!"); return NULL; // 或者用exit(1)终止程序 }
额外建议:处理fgets读取的换行符
fgets会把文件中的换行符\n也读进line里,如果不需要的话,可以去掉:
while(fgets(line, sizeof(line), f)!=NULL){ // 去掉换行符 line[strcspn(line, "\n")] = '\0'; // 后续处理... }
最后,记得在程序结束时释放所有分配的内存,避免内存泄漏哦!
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

