You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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;
}

其他关联问题修复

  1. 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);
}
  1. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 17:18:22