C语言汽车信息管理程序saveData与reload函数故障排查求助
汽车信息管理C程序saveData()与reload()函数异常排查及修复
核心问题分析
1. saveData()函数问题
当前saveData()仅保存了指针数组的地址、size和eSize,但指针地址是进程私有且临时的,下次程序启动时这些地址完全无效,根本未保存结构体中的实际汽车数据(make、model等字段),导致无法完整恢复数据。
2. reload()函数问题
- 读取了上次保存的无效指针地址并直接赋值给新分配的指针数组,触发非法内存访问,导致程序崩溃并产生随机错误码;
- 循环分配内存时,条件
i < size错误,size是指针参数,应使用i < *size,否则会基于指针本身的数值循环,造成内存分配越界; - 未正确读取结构体实际数据,仅读取无效指针地址,无法恢复汽车信息。
修复方案
修复saveData()函数
修改为保存结构体实际数据而非指针地址:
void saveData(AUTOMOBILE *a[], int eSize, int size) { FILE* fp = fopen("binaryDocument.bin", "wb"); if (fp == NULL) { printf("\nCould not save the information to a binary file\n"); system("pause"); return; } // 保存数组总容量与有效元素数 fwrite(&size, sizeof(int), 1, fp); fwrite(&eSize, sizeof(int), 1, fp); // 逐个写入有效元素的结构体数据 for (int i = 0; i < eSize; i++) { fwrite(a[i], sizeof(AUTOMOBILE), 1, fp); } fclose(fp); }
修复reload()函数
修改为读取结构体数据到新分配的内存中:
AUTOMOBILE** reload(AUTOMOBILE* a[], int* eSize, int* size) { *eSize = 0; FILE* fp = fopen("binaryDocument.bin", "rb"); if (fp == NULL) { printf("\nNo previous data found!\n"); system("pause"); return a; } printf("\nLoaded previous saved data successfully!\n"); system("pause"); // 读取数组总容量 fread(size, sizeof(int), 1, fp); // 分配指针数组内存 a = calloc(*size, sizeof(AUTOMOBILE*)); if (a == NULL) { printf("Allocation of pointer array failed...\n"); fclose(fp); exit(-1); } // 读取有效元素数 fread(eSize, sizeof(int), 1, fp); // 为有效元素分配内存并读取数据 for (int i = 0; i < *eSize; i++) { a[i] = calloc(1, sizeof(AUTOMOBILE)); if (a[i] == NULL) { printf("Allocation of memory at autos[%i] failed...\n", i); // 释放已分配的内存 for (int j = 0; j < i; j++) { free(a[j]); } free(a); fclose(fp); exit(-1); } fread(a[i], sizeof(AUTOMOBILE), 1, fp); } // 为剩余未使用的位置分配内存(与初始化逻辑保持一致) for (int i = *eSize; i < *size; i++) { a[i] = calloc(1, sizeof(AUTOMOBILE)); if (a[i] == NULL) { printf("Allocation of memory at autos[%i] failed...\n", i); freeMemory(a, *size); fclose(fp); exit(-1); } } fclose(fp); return a; }
其他关联问题修复
- compareChars()函数逻辑错误:qsort传入的是
AUTOMOBILE*指针数组,需提取结构体的make字段进行比较:
int compareChars(const void* a, const void* b) { const AUTOMOBILE* arg1 = *(const AUTOMOBILE**)a; const AUTOMOBILE* arg2 = *(const AUTOMOBILE**)b; return strcmp(arg1->make, arg2->make); }
- sortByCost()函数重复输出问题:修改为直接交换指针,避免重复输出相同成本的汽车:
void sortByCost(AUTOMOBILE *autos[], int eSize) { AUTOMOBILE* temp; for (int i = 0; i < eSize - 1; ++i) { for (int j = i + 1; j < eSize; ++j) { if (autos[i]->cost > autos[j]->cost) { temp = autos[i]; autos[i] = autos[j]; autos[j] = temp; } } } printf("\nAutomobiles sorted by cost (low to high): \n"); for (int i = 0; i < eSize; i++) { printf("%i\t%s\t%s\t%i\n", autos[i]->cost, autos[i]->make, autos[i]->model, autos[i]->yearBuilt); } }
验证说明
修复后:
- 退出程序时,
saveData()会将所有有效汽车的结构体数据完整写入二进制文件; - 启动程序时,
reload()会读取文件中的总容量、有效元素数,分配对应内存后将结构体数据加载到内存中; - 不再出现非法内存访问导致的崩溃,数据可完整保存与恢复。
内容的提问来源于stack exchange,提问作者C beginner
相关产品推荐
相关产品推荐

