2016-02-23 6 views
1

В моей реализации связанного списка моя вспомогательная функция deleteNode(Node*), которая удаляет внутренний класс Node экземпляров, бросает ошибку времени выполнения, «вызывая точку останова» в локальном отладчике Windows в VS 2015. Я стараюсь соответствовать моему new и delete операторов. Является ли область/ссылка ролью, которую я не понимаю?В каком контексте оператор удаления выдает ошибку?

Даже если есть логическая ошибка в clear() и deleteNode() получает передается nullptr, она не должна бросать ошибка удаления nullptr, а затем назначить nullptr для себя правильно? В чем проблема с удалением?

class LinkedList { 
public: 
    LinkedList() : head(nullptr) {} 
    ~LinkedList() { clear(); } 

    void push_front() { 
     head = createNode(head); 
    } 

    void clear() { 
     Node* current_node = head; 
     while (current_node != nullptr) { 
      Node* next_node = current_node->next; // buffer 
      deleteNode(current_node); 
      current_node = next_node; 
     } 
    } 

private:  
    struct Node { 
     Node(Node* next) 
      : next(next) {} 
     Node* next; 
    }; 
    Node* head; 
    Node* createNode(Node* next) { 
     return new Node(next); 
    } 
    void deleteNode(Node*& toDelete) { 
     delete toDelete; // ***VS 2015 puts breakpoint here*** 
     toDelete = nullptr; 
    } 
}; 

int main() { 
    auto A = LinkedList(); 
    A.push_front(); 
    A.clear(); 
    return 0; 
} 

Я удалил все атрибуты и методы, не относящиеся к ошибке. Этот фиктивный код по-прежнему вызывает ту же ошибку.

+0

Правило Пяти: Вам нужно пользовательские операции копирования и перемещения. – dyp

+0

@dyp Я не знаком с тем, о чем вы говорите. Не могли бы вы связать меня с ресурсом, объясняющим это или самим разобраться? – Aposhian

+1

Я думаю, что это не связано с вашей проблемой, но вызовет проблемы в будущем, если вы не обратили на это внимания. Фраза «правило пяти» или ранее «правило из трех» приведет вас ко многим статьям, таким как http://en.cppreference.com/w/cpp/language/rule_of_three – dyp

ответ

4

Проблема заключается в вашей функции clear(). Видите ли, вы думаете, что из-за того, как вы написали свою функцию deleteNode, все ваши узлы будут nullptr после clear. Это, к сожалению, не так. Вы копируете head в current_node, а копия головы (то есть current_node) превращается в nullptr, когда она удаляется, но head остается не нулевым. Позже деструктор пытается удалить его снова. Вызов удаления в уже освобожденной памяти приводит к неопределенному поведению.

Чтобы исправить, добавить

head = nullptr; 

в конце вашей ясной функции

+0

Спасибо. Просто уточнить, хотя я передаю указатель ссылкой на 'deleteNode', так как' current_node' является только копией 'head',' head' не устанавливается в 'nullptr'. Правильно? – Aposhian

+0

@ Апостиан: точно –

0

В каком контексте оператор удаления выдает ошибку?

A delete выражение может вызывать, если сам деструктор выбрасывает, или деструктор субобъекта. Но вы должны избегать метания деструктора.

А выражение delete может также иметь неопределенное поведение, если вы попытаетесь удалить указатель, который не указывает на действительный объект. Исключением является nullptr, который можно удалить. Типичные причины случайного удаления недопустимого указателя пытаются дважды удалить одно значение указателя или забыть инициализировать память. Неопределенное поведение может привести к чему угодно, включая ошибку.

В чем проблема с удалением?

Вы удаляете один и тот же указатель дважды. Вы можете проверить это, проверив значение в отладчике.