I'm trying to implement a Singly linked list class in C++. I've overloaded the assignment operator to clone the list. The cloning itself seems to work fine, but the program crashes during deletion of the cloned list, which leads me to suspect if something's wrong during the copy procedure.
Any help is highly appreciated. Here's the code for the overloaded = operator:
DLList& DLList::operator=(const DLList& iList)
{
Node *t = iList.head();
while(t != NULL)
{
push(t->data);
t = t->next;
}
return *this;
}
Here's the code for the push operation:
void DLList::push(int data)
{
Node *n = new Node;
n->data = data;
n->next = NULL;
//n->random = NULL;
n->next = _head;
_head = n;
//cout << "_head" <<_head->data<< "head->next" << (_head->next ? _head->next->data : 0)<<endl;
}
Here's the main code (where the crash happens) :
DLList *d = new DLList();
d->push(10);
d->push(20);
d->push(30);
d->push(40);
d->setRandom();
d->display("Original list"); // Displays the original list fine
DLList *d1 = new DLList();
d1 = d;
d1->display("Cloned list"); //Displays the cloned list fine
delete d; // works fine
delete d1; // Crashes here due to segmentation fault, invalid pointer access during delete called as part of destructor)
Code for destructor (if it helps):
~DLList()
{
while(_head != NULL)
{
Node *temp = _head;
_head = _head->next;
delete temp; // crashes here during first iteration for the cloned list
}
}
you are not using the assignment operator actually! You are just copying the pointer to the other pointer. Debugging your code (or just add traces) would have showed that
d
and d1
are the same So when you delete the second list you delete the same address twice.
You don't really need new
here:
DLList d;
d.push(10);
DLList d1 = d; // assignment is REALLY called
d1.display("Cloned list");
the objects will be deleted when you go out of scope of your variables
If you want to test in your context, keeping the new
, change
d1 = d;
by
*d1 = *d;
to activate assignment operator.
Another advice: factorize your copy code so it is shared between assignment operator and copy constructor, and the deletion code should be shared between destructor and assignment operator (to avoid memory leaks when assigning twice): Not tested, don't flame me if it doesn't compile, just tell me I'll fix it, I'm already overanswering here :)
DLList& DLList::operator=(const DLList& iList)
{
destroy(); // or you'll get memory leaks if assignment done twice
copy(iList);
return *this;
}
DLList& DLList::DLList(const DLList& iList)
{
_head = NULL; // set _head to NULL in all your constructors!!
copy(iList);
}
~DLList()
{
destroy();
}
void DLList::copy(const DLList& iList) // should be private
{
Node *t = iList.head();
while(t != NULL)
{
push(t->data);
t = t->next;
}
}
void DLList::destroy() // private
{
while(_head != NULL)
{
Node *temp = _head;
_head = _head->next;
delete temp; // crashes here during first iteration for the cloned list
}
_head = NULL; // calling destroy twice is harmless
}
d1 = d;
is NOT copying DLList. Instead, you just make d1
point to the list that d
pointing to. So, both d1
and d
are pointing to the same list. At the end of your program, you will delete the list twice, and make your program crash.
If you wish to use the assignment operator, you need to dereference your pointers. See here:
DLList *d1 = new DLList();
d1 = d; // <------------- This line
d1->display("Cloned list"); //Displays the cloned list fine
On the highlighted line, you're setting the pointer d1
to point to the same location as d
. This means that when you call delete
at the end of your code, you're trying to delete the same object ( d
in this case) twice.
To fix your code, you should dereference your pointers:
DLList *d1 = new DLList();
*d1 = *d; // <------------- Note the dereference applied to BOTH lists.
d1->display("Cloned list"); //Displays the cloned list fine
Alternatively, you should avoid using pointers entirely if you can. For your trivial example you could simply create your objects directly.
Your problem is the statement
d1 = d;
which does a pointer assignment, and makes d1
point to the same object as d
. The subsequent delete
statements cause the same object ( *d
) to be released twice. That is undefined behaviour (of which one symptom is a crash like you describe).
The above also does not invoke DLList
s copy constructor. If that is your intent, you need to do
*d1 = *d;
which makes the object pointed to by d1
a copy of the one pointed to by d
. The two delete
statements are also appropriate in this case.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.