C语言静态数组内存损坏:结构体数组读写异常原因咨询
问题原因分析
核心错误
你代码的问题出在save和load函数的fwrite/fread调用的第一个参数传值错误:
- C语言中,函数形参里的数组类型会自动退化为指针,因此
save/load函数里的menu本质是category*类型的局部指针变量,存储的是外部传入的菜单数组的首地址。 - 你调用
fwrite(&menu, ...)时,&menu取的是这个局部指针变量自身在栈上的地址,而不是指针指向的菜单数组的首地址,因此你写入文件的不是菜单数组的内容,而是栈上的随机内存数据。
调换变量顺序偶然生效的原因
这种表现是C语言未定义行为的偶然结果:
- 栈内存的分配规则是从高地址向低地址分配,你定义局部变量的顺序决定了它们在栈上的排布:
- 当你先定义
menu再定义tables时,menu数组在栈上的位置比局部指针变量menu的地址更高,你从指针地址开始写的内容完全碰不到menu数组的有效数据,因此写入文件的都是垃圾值,读出来自然为空。 - 当你先定义
tables再定义menu时,menu数组在栈上的位置刚好和你写的栈内存范围重合,因此碰巧把正确的菜单数据写入了文件,读取就得到了正确结果。这完全是巧合,不具备可移植性,换编译环境或编译参数就会失效。
- 当你先定义
修复方案
把save和load函数里的&menu改成menu即可,修正后的代码如下:
void save(category menu[]){ FILE* fp; fp = fopen("Menu","w+b"); // 直接传menu,即菜单数组首地址 fwrite(menu, sizeof(category), MAX_CATEGORY_NUM, fp); fclose(fp); } void load(category menu[]){ FILE* fp; fp = fopen("Menu","r+b"); // 直接传menu,即菜单数组首地址 fread(menu, sizeof(category), MAX_CATEGORY_NUM, fp); fclose(fp); }
内容的提问来源于stack exchange,提问作者David155
相关产品推荐
相关产品推荐

