C++ 丢失作用域时的唯一\u ptr读取访问冲突

C++ 丢失作用域时的唯一\u ptr读取访问冲突,c++,ifstream,unique-ptr,C++,Ifstream,Unique Ptr,我使用std::ifstream从二进制文件中读取字符数组,然后将字符数组重新解释为指向我的结构的指针,然后使其成为唯一的\u ptr。 除了unique_ptr超出范围之外,其他一切都正常工作,我会遇到读访问冲突 我这样做完全错了吗?我不确定为什么会发生错误。我对该数据只有一个唯一的ptr 我已经包含了产生错误的代码的基本版本 struct mystruct { int val = 0; double val2 = 5.6; std::string string = "

我使用std::ifstream从二进制文件中读取字符数组,然后将字符数组重新解释为指向我的结构的指针,然后使其成为唯一的\u ptr。 除了unique_ptr超出范围之外,其他一切都正常工作,我会遇到读访问冲突

我这样做完全错了吗?我不确定为什么会发生错误。我对该数据只有一个唯一的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
}
struct mystruct{
int-val=0;
双val2=5.6;
std::string=“test”;
};
int main()
{
//此处的括号仅用于封装此示例的范围
{
//试着打开阅读流
std::ifstream;
stream.open(“test.bin”,std::ios::binary | std::ios::in);
char*buffer=新字符[sizeof(mystruct)];
读取(缓冲区,sizeof(mystruct));
mystruct*pointer=reinterpret\u cast(缓冲区);
std::unique_ptr obj=std::unique_ptr(指针);
//读取结构数据没有问题

std::cout代码中有3种未定义的行为

首先,你假装在一个没有对象的地方有一个对象。你从来没有创建过
mystruct
;你只是分配了一些字节的内存。仅仅执行
重新解释
不足以创建
mystruct
。因此,任何使用
指针访问不存在的“对象”的行为都是错误的

第二,即使缓冲区中有一个,mystruct也不是简单的可复制的,所以你不能只是复制它的字节。你不能将一堆字节读入一个非简单的可复制对象。这是一个非简单的可复制非静态数据成员(即:
mystruct::string
)这使得它非常容易被复制

第三,你试图删除这个
mystruct
。但是这里没有
mystruct
,你正在删除一个不存在的东西。从技术上讲,这可能包含在#1中,但很可能是什么导致了你的代码彻底崩溃

如果您想知道为什么“读取结构数据没有问题”会起作用,那么
std::string
实现很有可能使用小字符串优化,如果字符串足够小,它会将字符串存储在
std::string
本身中。对于小字符串,按字节复制可能接近“工作”以允许您读取字符串数据


但这只是幸运而已。

你的程序表现出未定义的行为,通过传递给
delete
一个类型不同于
new
所分配类型的指针。实际上,它在
obj->string
之前表现出未定义的行为,通过在对象生命期开始之前访问对象的方式;你只是碰巧发生了不受影响(可能是由于小字符串优化)。有没有更好的方法将二进制文件读入具有唯一\u ptr的结构中?假设没有特定于类的
运算符new
,请使用
::运算符new
进行原始分配,然后使用placement new。您的结构包含的
std::string
不是,因此使用
fstream::write()进行写入和读取
fstream::read()
将不起作用。但您肯定无法从文件中读取
std::string
,这毫无意义。
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;
        }


    }
}