C++读写含vector成员的结构体向量到二进制文件报错如何解决
问题根因
你遇到的报错本质是不能直接对包含非POD(普通旧数据)类型的结构体做二进制裸读写:
std::vector属于非POD类型,内部存储的是指向堆内存的指针、容量、大小等控制信息,你直接file.write写info结构体的时候,只是把这些指针、控制信息的当前内存值写入了文件,并没有写入vector实际存储的MyStruct元素内容- 读取的时候你直接把二进制内容覆盖到新的
info实例的内存空间,会破坏vector的内部结构,后续vector析构、访问的时候就会触发访问越界错误,也就是你遇到的0xC0000005报错。
修复方案
你需要手动实现结构体的序列化/反序列化逻辑,逐个成员处理读写,特殊处理vector类型:
修改后的完整代码
#include <iostream> #include <fstream> #include <vector> #include <cstring> struct MyStruct { int a; }; struct info { char name[30]; int age; char bbl[20]; std::vector<MyStruct> my; }; // 序列化单个info对象到文件 void write_info(std::ofstream& file, const info& inf) { // 写入固定长度的基础成员 file.write(inf.name, sizeof(inf.name)); file.write(reinterpret_cast<const char*>(&inf.age), sizeof(inf.age)); file.write(inf.bbl, sizeof(inf.bbl)); // 先写入vector的元素个数 size_t my_size = inf.my.size(); file.write(reinterpret_cast<const char*>(&my_size), sizeof(my_size)); // 再逐个写入vector里的每个MyStruct元素 for (const auto& item : inf.my) { file.write(reinterpret_cast<const char*>(&item.a), sizeof(item.a)); } } // 从文件反序列化单个info对象 bool read_info(std::ifstream& file, info& inf) { // 读取固定长度的基础成员 if (!file.read(inf.name, sizeof(inf.name))) return false; if (!file.read(reinterpret_cast<char*>(&inf.age), sizeof(inf.age))) return false; if (!file.read(inf.bbl, sizeof(inf.bbl))) return false; // 先读取vector的元素个数 size_t my_size = 0; if (!file.read(reinterpret_cast<char*>(&my_size), sizeof(my_size))) return false; // 清空原vector,预留空间后逐个读取元素 inf.my.clear(); inf.my.reserve(my_size); for (size_t i = 0; i < my_size; ++i) { MyStruct item; if (!file.read(reinterpret_cast<char*>(&item.a), sizeof(item.a))) return false; inf.my.push_back(item); } return true; } void create(const std::vector<info>& test) { // 这里用trunc覆盖旧文件,避免追加导致格式错乱,如果你确实需要追加写入可以改回ios::app std::ofstream file("info.dat", std::ios::binary | std::ios::trunc); for (const auto& inf : test) { write_info(file, inf); } } int main() { info info1; std::vector<info> test; info1.age = 3443; std::cin >> info1.name; std::cin >> info1.bbl; MyStruct my; my.a = 4; info1.my.push_back(my); test.push_back(info1); std::cout << '\n'; create(test); test.clear(); { std::ifstream file("info.dat", std::ios::binary); info inf; while (read_info(file, inf)) { test.push_back(inf); } } for (size_t i = 0; i < test.size(); i++) { std::cout << "{ " << test[i].name << ", " << test[i].age << ", " << test[i].bbl << ", my数组长度: " << test[i].my.size() << ", my[0].a值: " << test[i].my[0].a << " } "; } std::cout << '\n'; return 0; }
额外注意事项
- 这种二进制序列化的文件不具备跨平台、跨编译器版本兼容性,不同环境下的结构体对齐规则、int/long等基础类型的长度可能不一样,如果需要兼容需要显式指定固定长度类型(比如
int32_t替代int)、关闭结构体对齐。 - 如果后续结构体成员更复杂,建议用专门的序列化库比如protobuf、flatbuffers来处理,避免手动写序列化逻辑出错。
内容的提问来源于stack exchange,提问作者Robert
相关产品推荐
相关产品推荐

