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

结构体指针数组写入二进制文件后单独读取失败的原因分析

问题分析:二进制文件读写结构体指针数组的异常问题

问题描述

定义了包含nLife和nDamage两个int变量的CHARACTER结构体,通过CreatCharacter()函数分配MAX个结构体实例并赋值,尝试将这些实例保存到二进制文件后读取。出现的异常是:创建文件后立即读取能正常工作,但单独执行读取操作时却失败。

代码片段

结构体定义

#define MAX 10

typedef struct
{
    int nDamage;
    int nLife;
} CHARACTER;

创建结构体实例的函数

int CreatCharacter(CHARACTER* pCharMan[], int max)
{
    for (int i = 0; i < max; i++)
    {
        pCharMan[i] = (CHARACTER*)malloc(sizeof(CHARACTER));
        if (pCharMan[i] == NULL)
        {
            printf("fail\n");
            return 0;
        }

        pCharMan[i]->nLife = rand() % 51 + 50;
        pCharMan[i]->nDamage = 0;
    }

    return pCharMan; // 此处存在类型不匹配错误:返回值应为int,实际返回指针数组
}

主函数(读写逻辑)

void main()
{
    FILE* fp, *op;
    srand((unsigned)time(NULL));
    CHARACTER* pCharMan[MAX];
    CHARACTER* testStruct[MAX];

    CreatCharacter(pCharMan, MAX);
    // ①
    //fp = fopen("charinfo.bin", "wb");                 // 若不注释①则读取正常
    //fwrite(pCharMan, sizeof(CHARACTER*), MAX, fp);
    //fclose(fp);

    // ②
    op = fopen("charinfo.bin", "rb");
    fread(testStruct, sizeof(CHARACTER*), MAX, op);     // 注释①仅执行②时读取失败
    fclose(op);                                         // charinfo.bin文件已存在
}

问题成因

核心错误在于写入文件的是结构体指针的内存地址,而非结构体的实际数据:

  • pCharMan是一个指针数组,数组中的每个元素是malloc分配的堆内存地址,指向实际的CHARACTER结构体数据。
  • 执行fwrite(pCharMan, sizeof(CHARACTER*), MAX, fp)时,写入的是这些内存地址值,而非地址指向的结构体内容。
  • 创建文件后立即读取时,当前进程的堆内存尚未被释放,读取的旧地址在当前进程的地址空间中仍然有效,能通过指针访问到对应的数据;但单独执行读取操作时,新进程的地址空间与之前的进程完全独立,读取的旧地址在新进程中是无效的(要么是未分配的内存,要么指向无关数据),因此读取失败。

另外,CreatCharacter函数存在明显错误:返回类型声明为int,但实际返回了pCharMan(指针数组),类型不匹配,正确的做法是成功时返回1,失败时返回0。

修正方案

要正确保存结构体数据,需要写入指针指向的结构体内容,而非指针本身:

修正写入逻辑

fp = fopen("charinfo.bin", "wb");
for (int i = 0; i < MAX; i++) {
    // 写入每个指针指向的结构体实际数据
    fwrite(pCharMan[i], sizeof(CHARACTER), 1, fp);
}
fclose(fp);

修正读取逻辑

op = fopen("charinfo.bin", "rb");
for (int i = 0; i < MAX; i++) {
    // 先分配内存,再读取结构体数据到分配的内存中
    testStruct[i] = (CHARACTER*)malloc(sizeof(CHARACTER));
    fread(testStruct[i], sizeof(CHARACTER), 1, op);
}
fclose(op);

同时修正CreatCharacter函数的返回值:

int CreatCharacter(CHARACTER* pCharMan[], int max)
{
    // ... 原有分配和赋值逻辑 ...

    return 1; // 成功返回1
}

内容的提问来源于stack exchange,提问作者dkskfktldi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 15:38:20