将vector<int>保存到bin文件读取得到随机数据,如何解决?
问题成因
- 你对非POD类型的二进制序列化逻辑完全错误:
std::vector作为动态容器,其对象本身仅存储指向堆上实际数据的指针、元素数量、容量三个元数据,真实的元素内容并不在vector对象的内存区间内。你直接对vector对象取地址写入sizeof(data)长度的内容,仅保存了vector的元数据(包括指向堆内存的指针值),完全没有写入真实存储的int元素。 - 第一个版本的输出1完全是偶然的未定义行为:你读写操作中间原
vint对象未被销毁,其指向的堆内存还未被回收/覆盖,你读出来的load_vint里的指针恰好和原vint指向同一块内存,所以碰巧拿到了正确值,但此时load_vint和原vint持有同一个堆指针,二者析构时会触发重复释放,只是第一个版本程序刚好在崩溃前执行完了所有输出。 - 第二个版本提前崩溃是因为未定义行为的后果暴露:封装到testing函数后,对象生命周期的变化让堆内存提前被覆盖/重复释放的问题直接触发程序崩溃,所以没执行到
done的输出就终止了。
修复方案
正确的vector序列化逻辑需要先存储元素数量,再存储所有元素的实际内容;读取时先读取元素数量给vector分配对应空间,再读取元素填充到vector中。你可以通过模板特化实现vector类型的专属读写逻辑,修复后的代码如下:
#include <iostream> #include <fstream> #include <vector> using namespace std; // 针对POD类型的通用保存函数 template <typename T> void save(string p_file, const T& data) { ofstream output(p_file, ios::binary | ios::out); output.write((char*)&data, sizeof(data)); output.close(); } // 针对vector的特化保存函数 template <typename T> void save(string p_file, const vector<T>& data) { ofstream output(p_file, ios::binary | ios::out); // 先写入元素数量 size_t size = data.size(); output.write((char*)&size, sizeof(size)); // 再写入所有元素的实际内容 output.write((char*)data.data(), size * sizeof(T)); output.close(); } // 针对POD类型的通用读取函数 template <typename T> T read(string p_file) { ifstream input(p_file, ios::binary | ios::in); T data; input.read((char*)&data, sizeof(data)); input.close(); return data; } // 针对vector的特化读取函数 template <typename T> vector<T> read(string p_file) { ifstream input(p_file, ios::binary | ios::in); // 先读取元素数量 size_t size; input.read((char*)&size, sizeof(size)); // 初始化vector分配对应空间 vector<T> data(size); // 读取所有元素到vector的存储空间中 input.read((char*)data.data(), size * sizeof(T)); input.close(); return data; } void testing() { vector<int> vint; vint.push_back(1); save< vector<int> >("test.bin", vint); vector<int> load_vint = read< vector<int> >("test.bin"); cout << vint[0] << endl; cout << load_vint[0] << endl; } int main() { testing(); cout << "done" << endl; return 0; }
注意:上述代码仅适用于存储POD类型(基础类型、仅含POD成员的结构体)的vector,如果vector存储的是std::string、自定义类等非POD类型,需要单独实现对应类型的序列化逻辑。
内容的提问来源于stack exchange,提问作者celphato
相关产品推荐
相关产品推荐

