C++跨文件读取含vector的类二进制文件失败问题排查
故障原因分析
1. 直接写入vector容器会保存无效指针
vector<vector<float>>是动态容器,它内部存的不是实际的矩阵元素,而是指向堆内存的指针、容器大小、容量这些元数据。当你直接把Matrix对象写入二进制文件时,存的只是这些元数据的当前内存地址:
- 同一cpp文件读写时,进程没退出,指针指向的堆内存还在,所以能正常读;
- 换独立cpp文件读时,新进程的内存空间和原进程完全不搭,原来的指针地址在新进程里是无效内存,一访问就触发内存错误,程序直接崩了。
2. 类的内存布局可能不一致
如果两个cpp文件的编译环境不一样——比如一个用Debug模式、一个用Release模式,或者编译器版本不同,甚至内存对齐选项(比如#pragma pack)有差异——都会导致Matrix类的内存布局变样:
- 比如Debug模式下编译器会给类成员加调试用的填充字节,Release模式没有;不同编译器的对齐规则也可能不同,这会让
int d和Mat的内存偏移位置不一样; - 读取时
d因为位置靠前可能能读对,但Mat的元数据读出来是错的,后续访问自然就崩了。
3. 没做正确的序列化/反序列化
你大概率是直接用fwrite(&matrix, sizeof(Matrix), 1, file)和fread(&matrix, sizeof(Matrix), 1, file)来读写对象,但这种方法只适用于POD类型(普通旧数据类型),带vector的类根本不属于这类。正确的操作应该是:
- 写入时:先写
d的值,再写矩阵的行数Mat.size(),接着写每行的列数Mat[i].size(),最后把所有float元素逐行逐列写进去; - 读取时:先读
d,再读行数和列数,然后给Mat重新分配空间(比如Mat.resize(rows); for(auto& row : Mat) row.resize(cols);),最后把float元素逐个读出来填到Mat里。
内容的提问来源于stack exchange,提问作者Sourin Dey
相关产品推荐
相关产品推荐

