结构体指针数组写入二进制文件后单独读取失败的原因分析
问题分析:二进制文件读写结构体指针数组的异常问题
问题描述
定义了包含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
相关产品推荐
相关产品推荐

