std::vector push_back 导致访问冲突
std::vector push_back results in access Violation
故事: 我正在制作一个共享库,将 C 代码作为包装器公开到在 VS 2008 中编译的 C++ 静态库,所以我依赖于该编译器。在我的图书馆中,我正在尝试制作一个非常简单的字典来通过共享图书馆边界传递数据。我不会传递实际的字典,只传递处理程序并提供访问其成员的函数。字典只是一个 std::vector 键值对。
问题: 每次尝试将键值对 push_back 放入字典时,我的程序都会崩溃。这是一个独立的演示代码(main.cpp 一个新的 Win32 控制台项目):
#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] = '[=12=]';
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
。通过在该行设置断点,我可以看到所有 key
、content0
、node0 和 test
都已定义并具有 correct values.
由于您使用 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
Dict* test = (Dict*)malloc(sizeof(Dict));
并不像您想象的那样。
malloc
分配一块内存,但不初始化它。所以稍后,当您调用 test->nodes.push_back
时,您正在调用未初始化的内存。未定义的行为。在你的情况下,它崩溃了。
这里的解决方案是用 new
分配 test
,这将同时初始化 test
和 test->nodes
。
Dict* test = new Dict;
更好的解决方案是询问为什么 test
是动态分配的。
故事: 我正在制作一个共享库,将 C 代码作为包装器公开到在 VS 2008 中编译的 C++ 静态库,所以我依赖于该编译器。在我的图书馆中,我正在尝试制作一个非常简单的字典来通过共享图书馆边界传递数据。我不会传递实际的字典,只传递处理程序并提供访问其成员的函数。字典只是一个 std::vector 键值对。
问题: 每次尝试将键值对 push_back 放入字典时,我的程序都会崩溃。这是一个独立的演示代码(main.cpp 一个新的 Win32 控制台项目):
#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] = '[=12=]';
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
。通过在该行设置断点,我可以看到所有 key
、content0
、node0 和 test
都已定义并具有 correct values.
由于您使用 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
Dict* test = (Dict*)malloc(sizeof(Dict));
并不像您想象的那样。
malloc
分配一块内存,但不初始化它。所以稍后,当您调用 test->nodes.push_back
时,您正在调用未初始化的内存。未定义的行为。在你的情况下,它崩溃了。
这里的解决方案是用 new
分配 test
,这将同时初始化 test
和 test->nodes
。
Dict* test = new Dict;
更好的解决方案是询问为什么 test
是动态分配的。