C++读写二进制存储的struct时出现Access violation异常如何解决?
问题根因
你遇到的访问违规错误核心是不能直接对包含std::string的结构体执行二进制读写操作:
std::string不属于POD(简单旧数据)类型,内部存储的是指向堆内存的字符串指针、长度、容量等元数据,你调用write写入文件的只是这些元数据(包括当时进程空间内的内存地址),并没有写入字符串的实际内容。- 读取时你把读到的无效地址直接赋值给新的
std::string对象,访问这个非法地址时就会触发内存访问违规。
同时sizeof(review)得到的只是两个std::string对象的固定占用大小,和字符串实际长度无关,你的偏移寻址逻辑本身也完全不生效。
解决方案
方案1:改用固定长度字符数组(适合需要随机访问的场景)
将结构体替换为固定长度的字符数组,使其成为POD类型,即可直接按固定偏移做二进制读写:
#include <iostream> #include <fstream> #include <cstring> using namespace std; struct review { char text[256]; // 按最大可能的字符串长度设置固定大小 char date[64]; }; void getRegistry(int i) { review reg; // 无需动态申请,栈上分配即可 ifstream file("test.txt", ios::binary); if (file) { file.seekg(i * sizeof(review), ios::beg); file.read(reinterpret_cast<char*>(®), sizeof(review)); cout << reg.text << endl; file.close(); } } void generateBinary() { ofstream arq("test.txt", ios::binary); review x; // 用字符串拷贝给字符数组赋值 strncpy(x.text, "asdasdasd", sizeof(x.text)-1); strncpy(x.date, "qweqweqwe", sizeof(x.date)-1); for (int i = 1; i <= 1000000; i++) { arq.write(reinterpret_cast<const char*>(&x), sizeof(review)); } arq.close(); } int main() { generateBinary(); getRegistry(2); return 0; }
方案2:自定义序列化逻辑(适合动态长度字符串场景)
如果需要保留动态长度的std::string,需要自行实现序列化逻辑,先写入字符串长度再写入字符串内容:
注意:该方案下每条记录长度不固定,无法直接按固定偏移做随机访问,若需要随机访问需额外建立索引表存储每条记录的起始偏移。
// 写单条review逻辑 void writeReview(ofstream& os, const review& r) { size_t text_len = r.text.size(); os.write(reinterpret_cast<const char*>(&text_len), sizeof(text_len)); os.write(r.text.data(), text_len); size_t date_len = r.date.size(); os.write(reinterpret_cast<const char*>(&date_len), sizeof(date_len)); os.write(r.date.data(), date_len); } // 读单条review逻辑 void readReview(ifstream& is, review& r) { size_t text_len; is.read(reinterpret_cast<char*>(&text_len), sizeof(text_len)); r.text.resize(text_len); is.read(r.text.data(), text_len); size_t date_len; is.read(reinterpret_cast<char*>(&date_len), sizeof(date_len)); r.date.resize(date_len); is.read(r.date.data(), date_len); }
内容的提问来源于stack exchange,提问作者Igor_Fam
相关产品推荐
相关产品推荐

