Search code examples
c++listlinked-listdestructor

Delete in C++ linked list results in an infinite loop


Edit

This is correct implementation of the List. Thank you guys especially Agent_L who helped me privately.

CORRECT LINKED LIST IMPLEMENTATION

#include <cstdio>
#include <cmath>
#include<iostream>
#include <stdio.h>
#include <string.h>
using namespace std;

class Node{
 friend class List;
public:
    Node(Node* next, int wrt){
        this->next = next;
        this->wrt = wrt;
    }

    Node(const Node& obiekt){
        this->wrt = obiekt.wrt;
        this->next = obiekt.next;
    }
     //NIE MA DESTRUKTORA BO NIE ALOKUJE ZADNYCH DANYCH !!!

    void show(){
        cout<<this->wrt<<endl;
    }




 private:
    Node* next;
    int wrt;

};


class List{

public:
List(int wrt){
    this->root = new Node(NULL, wrt);
}


    List(const List& list)
{
    // jesli pusty kopiujemy
    if (list.root == NULL)
    {
        this->root = NULL;
        return;
    }

    //tworzenie nowego korzenia
    this->root = new Node(NULL, list.root->wrt);

    Node* list_currentNode = list.root;
    Node* this_currentNode = this->root;
    while (list_currentNode->next != NULL)
    {
        // tworzenie nastepnika
        Node* newNode = new Node(NULL, list_currentNode->next->wrt);
        this_currentNode->next = newNode;
        this_currentNode = this_currentNode->next;
        list_currentNode = list_currentNode->next;
    }
}


void add(int wrt){
    Node* node = new Node(NULL, wrt);
    Node* el = this->root;
    while(el->next != NULL){
        //el->show();
        el = el->next;
    }
    el->next = node;
}

void remove(int index){
    Node* el = this->root;
    if(index == 0){
       this->root = el->next;
       delete el;
    }
   else{
    int i  = 0;
    while(el != NULL && i < index - 1){

        el = el->next;
        i++;
    }
     if(el!=NULL){
        Node* toRem = el->next;
        Node* newNext = toRem->next;
        el->next = newNext;
       delete toRem;
    }
}
}

void show(){
    Node* el = this->root;
    while(el != NULL){
        el->show();
        el = el->next;
    }
}

~List(){
    Node* currentNode = this->root;
    while (currentNode != NULL)
    {
        Node* nextNode = currentNode->next;
        delete currentNode;
        currentNode = nextNode;
    }
}


private:
    Node* root;

};

int main(){
    List* l = new List(11);
    l->add(22); l->add(33);
    l->show();
    cout<<endl;
    List* lala = new List(*l);
    lala->show();
    cout<<endl;
    lala->add(44);
    cout<<"lala before remove"<<endl;
    lala->show();
    lala->remove(1);
    cout<<"l before delete"<<endl;
    l->show();
    cout<<"lala before delete"<<endl;
    lala->show();
    delete l;
  /*  cout<<"l after delete   "<<endl;
    l->show(); */
    cout<<"lala after delete"<<endl;
    lala->show();
    return 0;
   }

I've implemented List and there is a problem. I've destructor in List which doesn't work as it should: please look at main and see "l after delete" it does print l list backwards.

The bigger problem is remove method without delelete inside it works as it should but when I try to uncomment delete el/delete to Rem I get into infinite loop.

Why these lines especially 87 (forget 100) cause the program crashes when I call l->remove(0)?

http://wklej.org/id/761056/ Lines 87 and 100

remove method and List destructor are important

void remove(int index){
    Node* el = this->root;
    if(index == 0){
       this->root = el->next;
    //   delete el;
    }
   else{
    int i  = 0;
    while(el != NULL && i < index - 1){

        el = el->next;
        i++;
    }
     if(el!=NULL){
        Node* toRem = el->next;
        Node* newNext = toRem->next;
        el->next = newNext;
       // delete toRem;
    }
}
}

 ~List(){
    Node* currentNode = this->root;
    while (currentNode != NULL)
    {
        Node* nextNode = currentNode->next;
        delete currentNode;
        currentNode = nextNode;
    }
}

Whole code

#include <cstdio>
#include <cmath>
#include<iostream>
#include <stdio.h>
#include <string.h>
using namespace std;

class Node{
 friend class List;
public:
    Node(Node* next, int wrt){
        this->next = next;
        this->wrt = wrt;
    }

    Node(const Node& obiekt){
        this->wrt = obiekt.wrt;
        this->next = obiekt.next;
    }
     //NIE MA DESTRUKTORA BO NIE ALOKUJE ZADNYCH DANYCH !!!

    void show(){
        cout<<this->wrt<<endl;
    }




 private:
    Node* next;
    int wrt;

};


class List{

public:
List(int wrt){
    this->root = new Node(NULL, wrt);
}


    List(const List& list)
{
    // jesli pusty kopiujemy
    if (list.root == NULL)
    {
        this->root = NULL;
        return;
    }

    //tworzenie nowego korzenia
    this->root = new Node(NULL, list.root->wrt);

    Node* list_currentNode = list.root;
    Node* this_currentNode = this->root;
    while (list_currentNode->next != NULL)
    {
        // tworzenie nastepnika
        Node* newNode = new Node(NULL, list_currentNode->next->wrt);
        this_currentNode->next = newNode;
        this_currentNode = this_currentNode->next;
        list_currentNode = list_currentNode->next;
    }
}


void add(int wrt){
    Node* node = new Node(NULL, wrt);
    Node* el = this->root;
    while(el->next != NULL){
        //el->show();
        el = el->next;
    }
    el->next = node;
}

void remove(int index){
    Node* el = this->root;
    if(index == 0){
       this->root = el->next;
    //   delete el;
    }
   else{
    int i  = 0;
    while(el != NULL && i < index - 1){

        el = el->next;
        i++;
    }
     if(el!=NULL){
        Node* toRem = el->next;
        Node* newNext = toRem->next;
        el->next = newNext;
       // delete toRem;
    }
}
}

void show(){
    Node* el = this->root;
    while(el != NULL){
        el->show();
        el = el->next;
    }
}

~List(){
    Node* currentNode = this->root;
    while (currentNode != NULL)
    {
        Node* nextNode = currentNode->next;
        delete currentNode;
        currentNode = nextNode;
    }
}


private:
    Node* root;

};

int main(){
    List* l = new List(10);
    l->add(12); l->add(13);
    l->show();
    cout<<endl;
    List* lala = new List(*l);
    lala->show();
    cout<<endl;
    lala->add(4);
    cout<<"lala before remove"<<endl;
    lala->show();
    lala->remove(0);
    cout<<"l before delete"<<endl;
    l->show();
    cout<<"lala before delete"<<endl;
    lala->show();
    delete l;
    cout<<"l after"<<endl;
    l->show();
    cout<<"lala after delete"<<endl;
    lala->show();
    return 0;
   }

Solution

  • First Part

    Following three statements are causing infinite loop..

    l->~List();
    cout<<"l after"<<endl;
    l->show();
    

    Because your destructor ~List() misses an important statement, which is...

    this->root = NULL;
    

    Which is the main reason for infinite loop. So here your full destructors goes..

     ~List()
     {
        Node* currentNode = this->root;
        while (currentNode != NULL)
        {
            Node* nextNode = currentNode->next;
            delete currentNode;
            currentNode = nextNode;
        }
    
        this->root = NULL;
    }
    

    Second Part

    Now as you have update above three lines into following...

    delete l;
    cout<<"l after"<<endl;
    l->show;              // We should never write this line in general practice..
    

    And considering that you're using above ~List() function. The reason for still program goes into an infinite loop is that delete l will de-allocate memory assigned to l. And you call l->show() (and as l is still pointing to an accessible linear address), so now this->root is pointing to some garbage location and thats why until it finds luckily while(el != NULL) condition NULL, it will stay in infinite-loop.