Thread: Destroying a linked list

  1. #1
    Registered User
    Join Date
    Sep 2009
    Posts
    29

    Destroying a linked list

    Hi all!

    I have a destructor implemented below. The problem is, it seems as if it deletes all of the items in the list properly but when the program gets to the final line of code, which is just the return statement in main, it throws an access violation. Can anyone help figure out why this is?

    Note: I can't put the whole program on here, because it's well over 800 lines. So, I'll just post an excerpt or two.

    Each "student" is a node. With data and a pointer (link) to the next node. I also have head and tail nodes which are the beginning and end of the list. I have double checked the constructor to make sure the tail points to NULL.

    Code:
    singlyLinkedList::~singlyLinkedList()
    {
    	student *temp;		//Used for traversing list
    	student *swap;		//Used for holding values while deleting list
    	if (head != NULL && tail != NULL)
    	{
    		swap = head;	
    		
    		while (swap != NULL)
    		{
    			temp = swap;
    			swap = swap->link;
    			delete temp;
    		}
    		head = NULL;
    		tail = NULL;
    	}
    }
    Thanks!!

    EDIT:
    As I mentioned, it seems as if the list is destroyed correctly. However, I noticed when the program reaches the end of main, it calls the destructor again, and the pointers for head and tail are both bad (not null).... With breakpoints, I've noticed that students (in main, reprinted below) gets destroyed before the cout statement, and then again at the end of the program... Does anyone know why it might be happening in that order?

    both students and classLists implement this linked list.

    Code:
    int main()
    {
    	//Initialize the list of classes
    	string classNames[22] = { "CSCE101", "CSCE 101L", "CSCE 150E", "CSCE150EL",
    							  "CSCE150EM", "CSCE150EML", "CSCE 155", "CSCE155H",
    							  "CSCE 156", "CSCE 230", "CSCE 230L", "CSCE 235",
    							  "CSCE 251", "CSCE 310", "CSCE 322", "CSCE 361",
    							  "CSCE 351", "CSCE 451", "CSCE 423", "CSCE 428",
    							  "CSCE 486", "CSCE 487" };
    
    	singlyLinkedList classLists[22];
    	singlyLinkedList students;
    
    	for(int i=0; i< 22; i++)
    	{
    		classLists[i].setClassName(classNames[i]);
    	}
    	students.setClassName("Student List");
    	parseData(classLists, students, 22);
    	
    	for (int i=0; i < 22; i++)
    		cout << classLists[i];
    
    	return 0;
    }
    If anyone wants to take a look at the whole code, I've included it as attachments.
    Last edited by maxsthekat; 09-23-2009 at 04:05 PM.

  2. #2
    Registered User
    Join Date
    Sep 2009
    Posts
    29
    registrations.txt will have to be renamed to registrations.dat in order to work correctly

  3. #3
    3735928559
    Join Date
    Mar 2008
    Location
    RTP
    Posts
    838
    you don't have a linked list, you have a static array. classnames is declared on the stack and should not be destroyed by you.

    Code:
    string *classnames = new string[22];
    needs to be destroyed by you.

  4. #4
    Registered User
    Join Date
    Mar 2009
    Posts
    399
    I haven't read your code, but you should create a list node class with a destructor that deletes the next list node in the list. That way the list will be deleted automatically when you delete the head of the list.

  5. #5
    Ex scientia vera
    Join Date
    Sep 2007
    Posts
    477
    Quote Originally Posted by m37h0d View Post
    you don't have a linked list, you have a static array. classnames is declared on the stack and should not be destroyed by you.

    Code:
    string *classnames = new string[22];
    needs to be destroyed by you.
    This is correct, but I highly recommend you use a vector of strings instead. The only downside is that until C++0x is final, you can't initialize the vector with an initializer list as you can with strings/arrays.

    But that downside is tiny when you consider the fact that the vector will do its own cleanup.
    "What's up, Doc?"
    "'Up' is a relative concept. It has no intrinsic value."

  6. #6
    Registered User
    Join Date
    Sep 2009
    Posts
    29
    classnames is just used for setting the name of each individual course within the classLists array (which is made up of singlyLinkedList objects, which contain my linked list). I don't destroy classnames on my own-- that's left to the compiler.

    So far, I've noticed that the "students" object (which is just a singlyLinkedList object I use to store all of the enrolled students, instead of having to traverse all of classLists to figure out if someone is enrolled) calls it's destructor before the cout statement in the main function, and then once again when main terminates.... It's extremely weird behavior, and I can't pin down why it would do that.

    I'd love to use vectors or lists or anything else out of the STL that would make my life easier, but unfortunately, some professors enjoy making their students re-invent the wheel

    Thanks again for all of your help, guys!

  7. #7
    Registered User
    Join Date
    Sep 2009
    Posts
    29
    Aha! Found it!

    For anyone interested in destructor precedence, here's a couple of great links:

    [11] Destructors, C++ FAQ Lite
    Why is destructor called twice? - C++

    The second one is definitely worth a read. Here's what was going wrong with my code:

    1) I don't have a copy constructor for my objects
    2) The call to parseData was pass by value (instead of by reference) for one of the objects
    3) Because of this, the destructor correctly calls for the temporary object created in the function. However, the object is not correctly returned to the one outside of the function (the calling object).
    4) When the calling object goes out of scope, the compiler looks at the bad pointers and hangs up an "out to lunch" sign, walks down the block, purchases a large mallet, walks back to the computer, and then proceeds to bash me in the head repeatedly.

    Moral of the story:

    If you are using pointers in a class, it is best to always
    1) Create a copy constructor (in case you use pass-by-value anywhere)
    2) Pass by reference (good ole "&", anywhere you don't want the copy constructor to be invoked).

  8. #8
    The larch
    Join Date
    May 2006
    Posts
    3,573
    2) Pass by reference (good ole "&", anywhere you don't want the copy constructor to be invoked).
    And to catch accidental attempts at pass by value, declare copy constructor and operator= private (or inherit from a suitable base class like boost::noncopyable).
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. C++ Linked list program need help !!!
    By dcoll025 in forum C++ Programming
    Replies: 1
    Last Post: 04-20-2009, 10:03 AM
  2. Following CTools
    By EstateMatt in forum C Programming
    Replies: 5
    Last Post: 06-26-2008, 10:10 AM
  3. Reverse function for linked list
    By Brigs76 in forum C++ Programming
    Replies: 1
    Last Post: 10-25-2006, 10:01 AM
  4. Template Class for Linked List
    By pecymanski in forum C++ Programming
    Replies: 2
    Last Post: 12-04-2001, 09:07 PM
  5. singly linked list
    By clarinetster in forum C Programming
    Replies: 2
    Last Post: 08-26-2001, 10:21 PM