Foxly
Foxly

Reputation: 1

C++ dynamic template queue "double free or corruption (out)" after calling destructor

I'm trying to implement a dynamic template queue in c++, but when I call the destructor I get a "double free or corruption (out)" error. Unfortunately I'm not allowed to change the file structure, or add any new methods/classes, or change the class/method declerations. I tried adding 5 items to a queue(rq1), before printing it out and destructing it, the print works fine, but I get an error when I destruct. Here is my code:

main.cpp

#include "resrcQueue.h"
#include <string>
#include <iostream>

using namespace std;

int main(){
  queueNode<string>* q1 = new queueNode<string>("apples",100);
  queueNode<string>* q2 = new queueNode<string>("lemons",200);
  queueNode<string>* q3 = new queueNode<string>("gold",10);
  queueNode<string>* q4 = new queueNode<string>("stone",11);
  queueNode<string>* q5 = new queueNode<string>("brick",12);

  resrcQueue<string> rq1;
  rq1.enqueue(q1);
  rq1.enqueue(q2);
  rq1.enqueue(q3);
  rq1.enqueue(q4);
  rq1.enqueue(q5);
  rq1.print();

  delete &rq1;

  return 0;
}

rsrcQueue.h

#ifndef RQUEUE
#define RQUEUE

#include <string>
#include <iostream>
#include "queueNode.h"

using namespace std;

template <class T>
class resrcQueue{
private:
  queueNode<T>* head;
  queueNode<T>* tail;

public:
  resrcQueue();
  ~resrcQueue();
  void enqueue(queueNode<T>* t);
  void dequeue();
  queueNode<T>* peek();
  void print();
  int tallyWeight();
  string calculateStorageRequirements();
};

#include "resrcQueue.cpp"

#endif

resrcQueue.cpp

#include "resrcQueue.h"
#include <string>
#include <iostream>

using namespace std;

template <class T>
resrcQueue<T>::resrcQueue(){
  head=NULL; tail=NULL;
}

template <class T>
resrcQueue<T>::~resrcQueue(){
  queueNode<T>* currNode=head;
  queueNode<T>*temp;
  int count=1;
  while(head){
    cout<<count<<endl;
    this->dequeue();
    count++;
  }
}

template <class T>
void resrcQueue<T>::enqueue(queueNode<T>* t){
  queueNode<T>*newNode=NULL;
  newNode = new queueNode<T>(t->getResrc(),t->getWeight());
  if(head){//not empty
    tail->next=newNode;
    tail=newNode;
  }else{//empty
    head=newNode;
    tail=newNode;
  }
}

template <class T>
void resrcQueue<T>::dequeue(){
  if(head){//not empty
    queueNode<T>* temp=head;
    head=head->next;
    delete temp;
  }else{//empty
    cout<<"EMPTY"<<endl;
  }
}

template <class T>
queueNode<T>* resrcQueue<T>::peek(){
  return head;
}

template <class T>
void resrcQueue<T>::print(){
  queueNode<T>* currNode=head;
  while(currNode){
    cout<<"Resource: "<<currNode->getResrc()<<endl;
    cout<<"Quantity: "<<currNode->getWeight()<<endl;
    currNode=currNode->next;
  }
}

template <class T>
int resrcQueue<T>::tallyWeight(){
  int totalWeight=-1;

  if(head){
    totalWeight=0;
    queueNode<T>* currNode=head;
    while(currNode){
      totalWeight+=currNode->getWeight();
      currNode=currNode->next;
    }
  }

  return totalWeight;

}

template <class T>
string resrcQueue<T>::calculateStorageRequirements(){
  int numNodes=0;
  queueNode<T>* currNode=head;
  while(currNode){
    numNodes++;
    currNode=currNode->next;
  }

  string r;

  if(this->tallyWeight()<100){
    r="wooden crate";
  }else if(this->tallyWeight()>200 && numNodes>5){
    r="steel crate";
  }else if(numNodes>5){
    r="silo";
  }else{
    r="LOGISTICS ERROR";
  }

  return r;
}

queueNode.h

#ifndef QNODE
#define QNODE

#include <string>
#include <iostream>

using namespace std;

template <class T>
class queueNode{
private:
  T resrc;
  int weight;
public:
  queueNode* next;
  queueNode(T r, int w);
  ~queueNode();
  T getResrc();
  int getWeight();
};

#include "queueNode.cpp"

#endif

queueNode.cpp

#include <string>
#include <iostream>
#include "queueNode.h"

using namespace std;

template <class T>
queueNode<T>::queueNode(T r, int w){
  next=NULL;
  resrc=r; weight=w;
  //cout<<"Init with weight: "<<weight<<", and resource: "<<resrc<<endl;
}

template <class T>
queueNode<T>::~queueNode(){
  cout<<"Resource Unit Destroyed"<<endl;
}

template <class T>
T queueNode<T>::getResrc(){
  return resrc;
}

template <class T>
int queueNode<T>::getWeight(){
  return weight;
}

makefile

main.out: main.cpp queueNode.h queueNode.cpp
    g++ -static -g main.cpp -o main.out
run: main.out
    ./main.out
clean: main.out
    rm main.out

Apologies if the question is a little specific and if I included too much code, I couldn't manage to duplicate the error which is why I posted the original code where I got the error, and I did struggle quite a lot of hours to fix it myself before posting it here, I will decrease the code length if it'll be better that way.

Upvotes: 0

Views: 323

Answers (1)

Ayjay
Ayjay

Reputation: 3433

There's a reason we ask people to make a MCVE - in the process of doing this you'll probably find the answer to your question.

When you take your program and strip out ALL of the unnecessary code and consolidate it into one file that still exhibits the bug, you get something like this:

#include <string>
using namespace std;

template <class T>
class resrcQueue{ };

int main(){
  resrcQueue<string> rq1;

  delete &rq1;
}

This still exhibits the bug. The reason for this is you can't delete stack variables. Remove the delete statement.

#include <string>
using namespace std;

template <class T>
class resrcQueue{ };

int main(){
  resrcQueue<string> rq1;
}

Upvotes: 3

Related Questions