std :: vector push_back导致访问冲突

时间:2016-03-02 20:28:02

标签: c++ visual-studio-2008 stdvector access-violation push-back

故事:我正在创建一个共享库,将C代码公开为VS 2008中编译的C ++静态库的包装器,因此我与该编译器绑定。在我的库中,我试图做一个非常简单的字典来通过共享库边界传递数据。我不会传递实际的字典,只是提供访问其成员的函数的处理程序。字典只是键值对的std :: vector。

问题:每次尝试将键值对推送回字典时,我的程序都会崩溃。这是一个独立的演示代码(一个新的Win32控制台项目的main.cpp):

#include "stdafx.h"

#include <cstdlib>
#include <vector>

typedef enum KeyType
{
    KeyType_CHAR = 0,
    KeyType_INT,
    KeyType_CHAR_PTR_AS_STRING
};

typedef enum ValueType
{
    ValueType_CHAR = 0,
    ValueType_INT,
    ValueType_CHAR_PTR_AS_STRING
};

struct DictNode
{
    ValueType value_type;
    void* value_unsafe_ptr;
    void* key_unsafe_ptr;
};

struct Dict
{
    KeyType key_type;
    std::vector<DictNode> nodes;
};

int _tmain(int argc, _TCHAR* argv[])
{
    /* Create Dict */
    Dict* test = (Dict*)malloc(sizeof(Dict));
    test->key_type = KeyType_INT;

    /* Add (0, "Zero") */
    int* key0 = (int*)malloc(sizeof(int));
    *key0 = 0;

    char* content0 = (char*)malloc(sizeof(char)*5);
    content0[0] = 'Z';
    content0[1] = 'e';
    content0[2] = 'r';
    content0[3] = 'o';
    content0[4] = '\0';

    DictNode node0;
    node0.value_type = ValueType_CHAR;
    node0.key_unsafe_ptr = key0;
    node0.value_unsafe_ptr = content0;

    test->nodes.push_back(node0); // BOOM

    /* Release memory */
    test->nodes.clear();
    free(key0);
    free(content0);
    free(test);

    return 0;
}

在第test->nodes.push_back(node0);行,我得到0xC0000005: Access violation reading location 0xcdcdcdc1。通过在该行设置断点,我可以看到所有keycontent0,node0和test都已定义并拥有correct values

2 个答案:

答案 0 :(得分:3)

Dict* test = (Dict*)malloc(sizeof(Dict));没有按照您的想法行事。

malloc分配一块内存,但不初始化它。所以稍后,当你调用test->nodes.push_back时,你会调用未初始化的内存。未定义的行为。在你的情况下,它崩溃了。

此处的解决方案是使用test分配new,这将初始化testtest->nodes

Dict* test = new Dict;

更好的解决方案是询问为什么test动态分配为开始。

答案 1 :(得分:1)

由于您使用C来分配内容,因此您无法获得C ++初始化行为。

因此,当您分配Dict时,std::vector仍然完全未初始化。您无法在不首先初始化的情况下使用它。只要您不想实际使用C ++,就应该使用placement new。

正确的解决方案是用C ++编程=&gt;使用new代替malloc。另外,除非你真的需要,否则不要将东西存储在堆上是一个好主意。

所以快速解决方法是添加:

new (&(test->nodes)) std::vector<DictNodes>;
分配测试后

更好的方法是完全停止使用malloc并使用

Dict *test = new Dict; // this automatically initializes the vector

或可能

Dict test; // no need to allocate on the heap if you don't need to