Указан неверный адрес для RtlvalidateHeap в Destructor для двусвязного списка - PullRequest
0 голосов
/ 18 января 2020

Я продолжаю получать эту ошибку, когда я запускаю свою программу.

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;
}

1 Ответ

0 голосов
/ 18 января 2020

Хотя вашего кода недостаточно для окончательного определения, учитывая симптомы и вашего деструктора, весьма вероятно, что вы не соблюдали правило 3 .

Правило 3 говорит вам, что если вам нужен конкретный деструктор c, например, потому что у вас есть указатель, вам нужно реализовать как минимум конструктор копирования и назначение копирования.

Почему?

  • У вас есть указатель Next в вашем классе.
  • Каким-то образом вы выделяете некоторую память и помещаете адрес в этот указатель (потому что если вы этого не сделаете, вы не удалите указанный объект в конце
  • Если у вас нет копии Конструкция и присвоение копии, когда бы вы ни копировали элемент List, вы будете копировать его указатель таким, какой он есть. Первый удаляемый объект (например, временный объект?) будет удалять указатель. И когда второй объект будет уничтожен, его Деструктор удалит уже удаленный указатель.

Теперь, если вам не нравится заботиться о правиле 3, есть лучшая альтернатива: избегайте использования необработанных указателей. Попробуйте использовать shared_ptr вместо этого. Эти указатели сами управляют памятью (например, удаляя объект, когда он больше не используется). В том числе в случае копирования и удаления копии.

...