【发布时间】:2019-10-04 08:41:11
【问题描述】:
我正在使用 std::ifstream 从二进制文件中读取 char 数组,然后将 char 数组重新解释为指向我的结构的指针,然后将其设为 unique_ptr。 一切正常,除非 unique_ptr 超出范围时,我会遇到读取访问冲突。
我做错了吗?我不确定为什么会发生错误。我在该数据上只有一个 unique_ptr。
我已经包含了产生错误的非常基本的代码版本。
struct mystruct {
int val = 0;
double val2 = 5.6;
std::string string = "test";
};
int main()
{
//brackets here just to encapsulate the scope for this example
{
//try to open the stream for reading
std::ifstream stream;
stream.open("test.bin", std::ios::binary | std::ios::in);
char* buffer = new char[sizeof(mystruct)];
stream.read(buffer, sizeof(mystruct));
mystruct * pointer = reinterpret_cast<mystruct*>(buffer);
std::unique_ptr<mystruct> obj = std::unique_ptr<mystruct>(pointer);
//ha no problem reading the struct data
std::cout << "read back: " << obj->string << endl;
stream.close();
}
//obj goes out of scope and throws a read access violation
}
我希望 unique_ptr 只是删除对象,不会抛出任何错误
**********编辑************************
感谢 cmets 和答案 - 基本上是在您的帮助下,我生成了我试图这样做的代码,并在此处列出了它,以防它对其他人有所帮助。
要点是:
* 如果从二进制读取和写入,则不建议在结构中使用 std::string,因为 std::string 的字节数未知。
* 需要在分配指针之前在内存中创建对象 - std::make_unique() 适合于此。
struct mystruct {
int val1 = 0;
double val2 = 5.6;
char somestring[10] = "string";
};
int main()
{
//brackets here just to encapsulate the scope for this example
{
//try to open the stream for reading
std::ifstream stream;
stream.open("test.bin", std::ios::binary | std::ios::in);
//hold the results in a vector
auto results = std::vector<std::unique_ptr<mystruct>>();
//read a vectory or mystructs from the binary file
while (!stream.eof())
{
//create the object - NOTE: make_unique initialises my struct
std::unique_ptr<mystruct> obj = std::make_unique<mystruct>();
//read from binary file into obj
if (!stream.read(reinterpret_cast<char*>(obj.get()), sizeof mystruct))
break;
//add the obj to th vector
results.push_back(std::move(obj));
}
stream.close();
for (auto& val : results)
{
cout << "read back: " << val->somestring << endl;
}
}
}
【问题讨论】:
-
你的程序表现出未定义的行为,通过将一个与
new分配的类型不同的指针传递给delete。实际上,它在obj->string的早期表现出未定义的行为,通过在对象的生命周期开始之前访问它;你只是碰巧侥幸逃脱(可能要感谢小字符串优化)。 -
有没有更好的方法将二进制文件读入具有 unique_ptr 的结构?
-
假设没有特定于类的
operator new,使用::operator new进行原始分配,然后使用placement new。 -
你的结构包含一个
std::string,它不是POD,所以用fstream::write()和fstream::read()写和读是行不通的。 -
但是你绝对不能从文件中读取
std::string,这没有意义。
标签: c++ ifstream unique-ptr