简体   繁体   English

C++ unordered_map 初始化读访问冲突

[英]C++ unordered_map initialization read access violation

I have a struct:我有一个结构:

struct Foo
{
    std::unordered_map<std::string, std::string> info;
    int count;
    int bar;
}

I am trying to initialize this struct on the heap as follows:我试图在堆上初始化这个结构,如下所示:

Foo* createFoo(int count, int bar)
{
    Foo* foo = (Foo*)malloc(sizeof(Foo));
    foo->info = std::unordered_map<std::string, std::string>(); // <- exception thrown here
    foo->count = count;
    foo->bar = bar;
    return foo;
}

I am getting the following exception thrown upon construction of the unordered_map :我在构建unordered_map抛出以下异常:

Exception thrown: read access violation. _Pnext was 0xCDCDCDD1.

I understand that MVS fills heap allocated memory with 0xCD which is why the _Pnext pointer has this value, but I don't understand why the unordered_map constructor isn't zero-ing these fields out.我知道 MVS 用0xCD填充堆分配的内存,这就是_Pnext指针具有此值的原因,但我不明白为什么unordered_map构造函数没有将这些字段清零。

I realize that the modern C++ way of doing this is with new /constructors but I am trying to write this code in a non-OOP procedural way with (basically) POD objects.我意识到现代 C++ 这样做的方式是使用new / 构造函数,但我试图用(基本上)POD 对象以非 OOP 程序方式编写此代码。

Am I initializing the map incorrectly?我是否错误地初始化了地图?

AC call of malloc malloc的AC调用

Foo* foo = (Foo*)malloc(sizeof(Foo));

does not invoke constructors for data members.不为数据成员调用构造函数。

So the data member所以数据成员

std::unordered_map<std::string, std::string> info;

was not constructed.没有建造。

And this statement with the copy assignment operator和这个带有复制赋值运算符的语句

foo->info = std::unordered_map<std::string, std::string>();

results in undefined behavior because there is not created the object foo->info .导致未定义的行为,因为没有创建对象foo->info

You have to use the operator new instead of malloc.您必须使用运算符 new 而不是 malloc。

For example例如

Foo* foo = new Foo();

malloc() do not initialize allocated memory and this is bad when allocating objects that have non-trivial constructors. malloc()不初始化分配的内存,这在分配具有非平凡构造函数的对象时很糟糕。

You should use new instead.你应该使用new代替。

Foo* foo = new Foo;

To deallocate objects allocated via new , you can use delete .要释放通过new分配的对象,可以使用delete

delete pointe_to_object;

malloc() doesn't create any object. malloc()不创建任何对象。 It just reserves some uninitialized memory.它只是保留了一些未初始化的内存。 There are no objects in that memory, those would have to be created with placement new .该内存中没有对象,必须使用放置new创建这些对象。

Now, operator= requires an existing object, because it's a member function (always).现在, operator=需要一个现有对象,因为它是一个成员函数(总是)。 By calling this operator on line foo->info = std::unordered_map<std::string, std::string>() you call operator on non-existing object.通过在foo->info = std::unordered_map<std::string, std::string>()行上调用此运算符,您可以在不存在的对象上调用运算符。

The solution is to not go against the language and use new as you are supposed to:解决方案是不要违背语言并按照您的预期使用new

Foo* createFoo(int count, int bar)
{
    Foo* foo = new Foo;
    // unnecessary now, the object is already constructed and default-initialized
    // foo->info = std::unordered_map<std::string, std::string>(); 

    // ints are constructed, but not initialized
    foo->count = count;
    foo->bar = bar;
    return foo;
}

You could also use malloc with placement new , but that's only useful if you need memory without actual objects (eg in vector implementation).您也可以将malloc与放置new一起使用,但这仅在您需要没有实际对象的内存时才有用(例如在向量实现中)。


Note: it's a bad smell to use raw new in modern C++ (well, 9 years old, but as modern as std::unordered_map ).注意:在现代 C++ 中使用 raw new很糟糕(嗯,9 岁了,但和std::unordered_map一样现代)。 Use smart pointers and STL containers instead.请改用智能指针和 STL 容器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM