Jake Psimos
Jake Psimos

Reputation: 640

Access Violation in Linked-List after copy constructor

I created a Linked-List in C++ and I am getting an access violation when inserting new item into the list.

The list works perfectly if the copy-constructor is never called and the original list is used throughout the program execution.

I am getting the error in the insert method after the call-by-value function 'outList' creates a copy of the list to manage in it's scope.

The list maintains a cursor (pointer) to a ListElement that is the active element. The list contains methods such as 'gotoNext' and 'gotoPrior' etc etc. The objective of the copy constructor is to create a deep copy of the list and maintain the cursor's position in the copy.

Before reading the code, here is the stack trace, as you can see, the program crashes after adding only one element to the list.

LinkedListExample.exe!LinkedList<char>::insert(const char & item, int position) Line 71 C++
LinkedListExample.exe!LinkedList<char>::LinkedList<char>(const LinkedList<char> & src) Line 35  C++
LinkedListExample.exe!main() Line 62    C++

Here is the Main()

void main()
{
    LinkedList<char> testList;      // Test list
    char insertChar;
    do{
        cin >> insertChar;
        outList(testList);
        testList.insert(insertChar, 0); //0 means insert after cursor, -1 insert before.
    }
    while(insertChar != 'q')
}

Here is Outlist

template <typename Type>
void outList(LinkedList<Type> list) 
{
    char tmp;
    if (list.empty())
       cout << "Empty list" << endl;
    else
    {
        list.gotoBeginning();
        do
        {
            tmp = list.retrieve();
            cout << tmp << " -> "; 
        }
        while (list.gotoNext());
        cout << endl;
    }
}

Here is LinkedList copy constructor:

template <typename Type>
LinkedList<Type>::LinkedList(const LinkedList &src){
    if(src.head == NULL){
        head = NULL;
        cursor = NULL;
    }else{
        ListElement *iterator = src.head;
        ListElement *placeHolder = src.cursor;
        int numHops = 0;
        if(iterator->next == NULL){
            numHops = 1;
        }else{
            while(iterator != placeHolder){
                numHops++;
                placeHolder = placeHolder->next;
            }
        }
        iterator = src.head;
        while(iterator != NULL){
            insert(iterator->element, 0);
            if(iterator->next != NULL){
                iterator = iterator->next;
            }else{
                break;
            }
        }
        gotoBeginning();
        if(numHops != 0){
            for(int i = 0; i < numHops; i++){
                gotoNext();
            }
        }
    }
}

Here is LinkedList insert:

template <typename Type>
void LinkedList<Type>::insert(const Type &item, int position){
    if(head == NULL){
        ListElement *newElement = new ListElement(item, NULL);
        newElement->next = NULL;
        head = newElement;
        cursor = head;
    }else if(position == 0){
        if(head->next == NULL){
            cursor = head;
        }
        //Create a new ListElement after the current.
        ListElement *newElement = new ListElement(item, NULL);
        //Preserve link (if there is one)
        if(cursor->next != NULL){
            newElement->next = cursor->next;
        }
        cursor->next = newElement;
        cursor = newElement;
    }else if(position == -1){
        //Add a new element before the current.
        ListElement *newElement = new ListElement(item, NULL);
        if(head->next == NULL || (cursor == head && cursor != NULL)){
            //Special case. There is only one node.  Must update head pointer.
            newElement->next = head;
            head = newElement;
            cursor = newElement;
        }else{
            //Node will be put between two other nodes.
            ListElement *iterator = head;
            while(iterator->next != cursor){
                iterator = iterator->next;
            }
            newElement->next = iterator->next;
            iterator->next = newElement;
            cursor = newElement;
        }
    }//end if line 24
}

For your reference, the stack trace tells me line 71 is the crash spot. Here is that line from the code block 'insert'...

else if(position == 0){
            if(head->next == NULL){
                cursor = head;
            }
            //Create a new ListElement after the current.
            ListElement *newElement = new ListElement(item, NULL);
            //Preserve link (if there is one)
            if(cursor->next != NULL){ //LINE 71 LINE 71 LINE 71 LINE 71
                newElement->next = cursor->next;
            }

Upvotes: 1

Views: 141

Answers (2)

klbm9999
klbm9999

Reputation: 41

try this code in place of line 71

else if(position==0){

ListElement *newElement = new ListElement(item,NULL);

if(head->next==NULL){
  cursor = head;
}
else{
  while (cursor->next!=NULL) { //placing the cursor on the last node inserted.
  cursor = cursor->next;
}
newElement->next = cursor->next;
cursor->next = newElement;
cursor = newElement;
    }
}

Upvotes: 0

wisalam
wisalam

Reputation: 36

In your copy constructor, if src.head != null, then head and cursor are not initialized when you first call insert. You probably meant to initialize them to NULL.

Upvotes: 2

Related Questions