【问题标题】:std::vector push_back results in access Violationstd::vector push_back 导致访问冲突
【发布时间】:2016-06-15 21:47:50
【问题描述】:

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

问题:每次我尝试将键值对 push_back 到字典中时,我的程序都会崩溃。这是一个独立的演示代码(一个新的 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-&gt;nodes.push_back(node0); 行,我得到0xC0000005: Access violation reading location 0xcdcdcdc1。通过在该行设置断点,我可以看到所有keycontent0、node0 和test 都已定义并具有correct values

【问题讨论】:

  • 如果这是一个 C++ 程序,你为什么要使用 malloc
  • 因为我将值存储为 void*,所以使用 set/get 函数(不在示例代码中)确保类型安全,该函数使用 ValueTypeKeyType 枚举设置/检查类型.
  • 如果你真的需要void*指针(注意:你不应该需要它们),你可以使用reinterpret_castnew分配的指针中获取它们

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


【解决方案1】:

Dict* test = (Dict*)malloc(sizeof(Dict)); 并没有按照你的想法去做。

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

这里的解决方案是用new分配test,这将同时初始化testtest-&gt;nodes

Dict* test = new Dict;

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

【讨论】:

    【解决方案2】:

    由于您使用 C 来分配东西,因此您不会获得 C++ 初始化行为。

    因此,当您分配 Dict 时,std::vector 仍然完全未初始化。不先初始化就不能使用它。只要您不想实际使用 C++,就应该为此使用placement new。

    正确的解决方案是用 C++ 编程 => 使用 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-05-22
      • 2023-03-08
      • 2023-03-15
      • 1970-01-01
      • 2023-03-21
      • 2011-04-19
      • 1970-01-01
      相关资源
      最近更新 更多