原始向量删除引发异常

时间:2016-04-27 18:43:17

标签: c++ vector

问题是标题,当在删除指令之前调试时我可以看到指针(向量)没问题,我甚至可以通过VC ++ Express2013立即窗口修改它的值,但是在删除之后它会抛出例外:

Unhandled exception at 0x55ACDF62 (msvcp120d.dll) in BTREE.EXE: 0xC0000005: Access violation writing location 0xABABABAB.

我的矢量是这个类的矢量:

template<class Key, class Value>
class Pair{
public:
Pair(){
    key = Key();
    value = Value();
}

Pair(Key key, Value value){
    this->key = key;
    this->value = value;
}

Key key;
Value value;
};

在模板中我使用int作为键,使用std :: string作为值,向量仅通过此方法分配:

Node(unsigned int max){
    nelements = 0;
    nchilds = 0;
    /*reserva espaço para os elementos e os nós filhos, cada vetor possui uma espaço adicional reservado*/
    elements = new Pair<Key, Value>[max];
    childs = new Node<Key, Value>*[max + 1];
    this->max = max;

    for (unsigned int i = 0; i < max + 1; i++)
        childs[i] = nullptr;
}

使用此向量的更复杂的操作在这里:

        left->nelements = middle;
    memcpy(left->elements, elements, sizeof(Pair<Key, Value>) * middle);
    if (!leaf()){
        left->nchilds = middle + 1;
        memcpy(left->childs, childs, sizeof(Node<Key, Value>*) * left->nchilds);
    }

这是析构函数:

~Node(){
    for (unsigned int i = 0; i < nchilds; i++)
            delete childs[i];
    delete[] childs;
    delete[] elements;
}

感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

异常表示您的代码(或者更确切地说是CRT)尝试在值为0xABABABAB的内存位置写入。在调试器下,Visual Studio设置此值以帮助查找错误。这意味着:

Used by HeapAlloc() to mark "no man's land" guard bytes after allocated heap memory

因为此异常源自delete,所以它意味着您通过覆盖某些内存缓冲区而损坏了堆,或者您尝试删除悬空指针。

一件看起来很可疑的事情是你使用memcpy来复制elements - 你应该只记得琐碎的类型。要检查是否是这种情况,请使用静态断言:

static_assert(std::is_trivially_copyable<Pair<Key, Value>>::value, "must be TriviallyCopyable type");

使用std::copy总是更好 - 它会将memmove用于TriviallyCopyable类型,否则将逐个复制元素。

为防止出现此类错误,您应该使用std::vector而不是动态数组,如果需要指针,则可以使用std::unique_ptr。结合<algorithm>标题中的各种功能。

答案 1 :(得分:0)

我看到你复制了分配的内存。

 memcpy(left->elements, elements, sizeof(Pair<Key, Value>) * middle);
    if (!leaf()){
        left->nchilds = middle + 1;
        memcpy(left->childs, childs, sizeof(Node<Key, Value>*) * left->nchilds);
    }

Node个实例到另一个?

在这种情况下,你确定只释放一次分配的指针吗?