Hello, I'm having an issue with delete[]. I have class LinkedList, and I'm trying to work with an array of Linked Lists here. When I call delete[] on my array, I get a seg fault, and valgrind basically tells me that there's a lot of invalid reads/deletes. I think it has something to do with the fact that my LinkedList destructor (called implicitly because my Linked Lists are on the stack) already deleted some of the stuff that delete[] is trying to delete... but I can't seem to find anything wrong with my Linked List destructor.
You haven't posted enough code to find the seg fault but as a precaution you can always check a pointer before you try to access it to narrow things out because simple things like that CAN cause a seg fault.
For example:
1 2 3 4 5 6 7 8 9 10 11 12 13
~LinkedList()
{
if (size == 0)
return;
Node* temp = head;
while (temp != NULL)
{
head = head->next; // can cause seg fault
delete temp;
temp = head;
}
}
I might be extra paranoid but I always check a pointer before accessing it unless I am 100% sure it's valid so I would try:
if (head)
head = head->next;
This is doesn't look like it's the problem and I am probably just too cautious but still. I honeslty dont even use C++ that much anymore but when I do I make sure to be careful, even if it reduces efficiency. Seg faults suck, even with debugging programs.
I realize that this is not the problem but he might be trying trying to access a null pointer somewhere else. When people wonder why they have seg faults I like to remind them that something as simple as accessing a pointer can be the culprit.
He thinks it's the delete but deleting a null pointer does not cause a seg fault.
I think the problem may be in your copy constructor. The lines
1 2
array[0] = listOne;
array[1] = listTwo;
probably do shallow copies, so array[0] and listOne refer to the same data. The delete[] may work just fine, but when listOne and listTwo go out of scope, the data in the lists get deleted again, and the core dump occurs.
Without seeing your LinkedList class template, I can't say for sure, but I suspect you did not write a copy constructor. You should. If you didn't, the default copy constructor will copy listOne to array[0] field by field. Unfortunately, your fields head and tail are pointers to dynamically allocated memory, so when the fields are copied, you have 2 lists pointing to the same dynamic memory locations.
Your copy constructor should do a deep copy--not copy the head and tail pointers, but traverse the actual linked lists and make dynamically allocated copies each of the elements. Then the head and tail elements should be assigned to the head and tail of the new linked lists.
That's the correct way to do it. If you are looking for a quick and dirty way to verify that the copy constructor is your problem, just pushFront on array[0] and array[1] and get rid of listOne and listTwo. If the core dump disappears, it will show that the copy constructor is your problem.
Everything I said earlier about a copy constructor needs to be said about the assignment operator. Your code actually uses the assignment operator (I frequently confuse the two in my mind). You actually wrote an assignment operator, but it needs to use deep copy semantics.
Write a function that does a deep copy. The copy constructor will call this new function. The assignment operator, on the other hand, will first check to make sure the lists aren't identical (&list != this), and if not identical will delete its own data and then call the deep copy function.
With dynamically allocated member data, you need a copy constructor (you don't have this), an assignment operator (needs to be fixed) and a destructor (you have this).
I noticed something in your getFront() function. If you have no elements in your list, it doesn't return anything meaningful. You might want to change the prototype to something like bool getFront (T& retVal);
Or else you need to return an empty T value or something like you did in end(). Realize this only works for data types that have default constructors (no arguments).
Thanks very much! That really helped me understand what's going on; I appreciate it. Also, if you happen to see anything wrong with my remove method, feel free to let me know as that's what I'm now having trouble with. It doesn't seem to be properly setting head and tail as it should.
If there is only one Node in the list, spot->next will be NULL, and the body of the for loop will never execute. if the item you're trying to remove is the only item in the list, it will not be removed.
If there is more than one Node in the list, the tail will never be checked because the tail's next pointer is equal to NULL, and the body of the for loop will not execute for the tail.