Установка указателя на `nullptr` не предотвращает двойное удаление? - PullRequest
0 голосов
/ 14 июля 2020

У меня есть реализация связанного списка, в которой у меня есть класс LinkedList, содержащий член с именем head_, который является указателем на LinkedListNode. LinkedListNode, очевидно, содержит член с именем next_, который я могу использовать для перехода по списку.

У меня есть деструктор ~LinkedList, который начинается с head_ и проходит по списку delete - все указатели на LinkedListNode по ходу:

~LinkedList() {
  LinkedListNode *thru = head_;
  while (thru != nullptr) {
    LinkedListNode* toDelete = thru;
    thru = thru->next;
    delete toDelete;
    toDelete = nullptr; // LINE *
  }

Все работает нормально. Мой вопрос о том, что произошло, когда я подумал, что буду в безопасности, и вставлю деструктор для класса LinkedListNode, например:

~LinkedListNode() { 
    if (next_ != nullptr) // LINE **
        delete next_;
}

Это вызывает ошибку переполнения стека, которая, как я предполагаю, потому что я пытаюсь удвоить delete указатели next_, один раз из LinkedList и один раз из LinkedListNode.

Мой вопрос: не следует устанавливать указатель toDelete на nullptr в строке (*), плюс проверка if() в строке (**), предотвратить ошибку двойного удаления?

1 Ответ

2 голосов
/ 14 июля 2020

Ваша проблема заключается в следующем:

~LinkedListNode() { 
    if (next_ != nullptr) // LINE **
        delete next_;
}

Представьте, что у вас есть связанный список 5, 4, 3, 2, 1, и ваша голова должна быть 5, следующим будет 4, 3, и так далее. Когда вы вызываете функцию, вы должны удалить 4, а все остальное останется в вашей системе, у вас нет возможности удалить 3, 2, 1 и так далее, вы удалили единственное, что указывает на них, вы не имеют к ним доступа. Многие люди предлагают рекурсивное решение, ну, честно говоря, это не сработает, если вы сделаете это в деструкторе, если вы действительно хотите, вам понадобится другая функция, например:

void deleteLinkedList(Node* head){
    if(head == nullptr)return;
    Node* temp = head->next;
    delete head;
    deleteLinkedList(temp);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...