Search code examples
c++memory-leakslinked-listdeque

Avoid memory leak when removing last node from deque using linkd list


For my homework, I need to make methods that add (append) and remove (serve) nodes from a Deque. However, when trying to serve the last node I struggle with memory leaks since I don't know how to retrieve the node that's not being used anymore to the system. Here's the code for the method.

void Deque::serveAtRear(int &x)
{
  if(empty())
  {
      cout << "Fila Vazia" << endl;
      exit(0);
  }
  else
  {
      DequePointer q;         //Pointer before p
      q = head;               //q starts at the deque's head
      p = head->nextNode;     //Pointer for the next node

      if(q->nextNode==NULL)   //If there's only one node
      {
         x = q->entry;        //x will receive the value of the removed node to print it afterward
         head = tail = NULL;
         delete p;            //I don't know if I'm using the "delete" right
      }
      else
      {
         while(p->nextNode != NULL)
         {
             p = p->nextNode;
             q = q->nextNode;
             if(p->nextNode==NULL)
             {
                 q->nextNode=NULL;
             }
         }
         x = p->entry;
         delete p->nextNode;
     }
     delete q->nextNode;
  }

}

To add nodes I have this method:

void Deque::appendAtFront(int x)
{

  if(full())
  {
     cout << "FULL" << endl;
     exit(0);
  }
  else
  {
     p = new DequeNode;
     p->entry=x;
     if(p == NULL)
     {
         cout << "Can't insert" << endl;
         exit(0);
     }
     else if(empty())
     {
         head = tail = p;
         p->nextNode=NULL;
     }
     else
     {
         p->nextNode=head;
         head = p;
     }
  }
}

Also I can't use the "deque" lybrary


Solution

  • Generic answer to how avoid leaks is: avoid manual memory allocation.

    For example you can use smart pointers, e.g. std::unique_ptr and instead of calling new DequeNode call std::make_unique<DequeNode>(). Compiler will then point places where your code needs to be adapted, as you will limit yourself so that each of your DequeNode(s) will be owned by just one unique_ptr at the same time. Example pop function (where head and DequeNode.next are uniuque_ptrs) based on your serveAtRear:

    if (!head)
    {
        return;
    }
    DequeNode* q;          //Pointer before p 
    DequeNode* p;          //will be tail eventually 
    q = head.get();        //q starts at the deque's head 
    p = q->next.get();     //Pointer for the next node 
    
    if(!p)   //If there's only one node 
    {       
            x = q->entry; //x will receive the value of the removed node to print it afterward 
            head.reset(); // hear we release DequeNode pointed by head
    }       
    else    
    {       
            while(p->next) 
            {       
                    q = p;  
                    p = q->next.get(); 
            }       
            x = p->entry; 
            q->next.reset(); // here we release tail (i.e. p)
    }       
    
    

    Of course implementation of push needs to be adopted too :).