首页 > 解决方案 > 在双向链表的析构函数中为 RtlvalidateHeap 指定的地址无效

问题描述

运行程序时,我不断收到此错误。

HEAP[PA1.exe]: Invalid address specified to RtlValidateHeap( 00C40000, 00C48880 )
PA1.exe has triggered a breakpoint.

我将它缩小到我的析构函数,但我不确定它为什么会导致它。


List::~List()
{
    if (!nullptr) {
        Item* toDelete = Head;
        while (toDelete != NULL) {
            Item* next = toDelete->Next;

                delete toDelete;
            toDelete = next;
        }
    }

编辑:我看到我的问题出在我的构造函数中,但是我不确定我需要改变什么。当我开始进行深层复制时,就会发生错误。所以我的猜测是它的复制构造函数。

List::List()
{
    Head = 0;
    Prev = 0;
    Next = 0;

}

List::~List()
{
    Item* move = Head;
    while (Head)
    {
        Head = move->Next;
        delete move;
        move = Head;
    }
}

List::List(const List& copy) 
{
    Head = copy.Head;
    Next= copy.Next;
    Prev= copy.Prev;


}

List& List::operator=(const List& t)
{
    Head = t.Head;
    Prev = t.Prev;
    Next = t.Next;
    return *this;
}

标签: c++visual-c++linked-listdestructordoubly-linked-list

解决方案


虽然您的代码不足以确定结论,但查看症状和析构函数,您很可能没有遵守3 的规则

规则 3 告诉你,如果你需要一个特定的析构函数,例如因为你有一个指针,你至少需要实现复制构造函数和复制赋值。

为什么 ?

  • 您的班级中有一个指针 Next
  • 不知何故,您分配了一些内存并将地址放入该指针中(因为如果您不这样做,您就不会在最后删除指向的对象
  • 如果您没有复制构造和复制分配,那么当您 cpy 一个 List 元素时,您将照原样复制它的指针。第一个要删除的对象(例如临时对象?)将删除指针。当第二个对象被销毁时,它的析构函数将删除一个已经被删除的指针。

现在,如果您不喜欢注意 3 的规则,有一个更好的选择:避免使用原始指针。尝试shared_ptr改用。这些指针自己管理内存(例如,当不再使用对象时将其删除)。包括在复制和删除副本的情况下。


推荐阅读