Auxive
Auxive

Reputation: 63

Pointer losing reference to previous node C++

I was writing a program to learn doubly linked lists. The problem I can't seem to debug is that the debugger gives me a write access violation and states that either the prevNode->next or nextNode->prev are pointing to a null. This happens as soon as you try to delete a node from nth position. I have removed some parts of the code for this post to make it shorter and easier to read, so some variables may seem unused.

The part that the debugger usually stops at is the last line before you delete the node:

nextNode = nodePtr->next;
prevNode = nodePtr->prev;
nextNode->prev = prevNode;
prevNode->next = nextNode;
delete(nodePtr);

I know for deleting nodes in the beginning and end of a list will require different code (if statement) to make sure prevNode->next and nextNode->prev are not set to a node that does not exist. The problem is that it's giving me those errors even when I'm trying to delete a node that isn't in the beginning or end of a list.

Any help or a push in the right direction would be much appreciated!

#include <iostream>
using namespace std;

int main() {

    struct ListNode {
        int value;
        ListNode *next;
        ListNode *prev;
    };

    ListNode *head = nullptr;
    ListNode *newNode = nullptr;
    ListNode *nodePtr = nullptr;
    ListNode *prevPtr = nullptr;
    ListNode *nextNode = nullptr;
    ListNode *prevNode = nullptr;

    char ch = 'q';
    int val;
    int pos;

    do
    {
        cout << "h-delete from position" << endl;
        cout << "i-insert" << endl;
        cout << "p-print" << endl;
        cout << "q-quit" << endl;

        cin >> ch;

        switch (ch) {

        case 'i':

            cout << "inserting ... \n";
            cout << "Enter an integer: ";
            cin >> val;

            newNode = new ListNode;
            newNode->value = val;
            newNode->next = nullptr;

            if (head == nullptr) {
                head = newNode;
            }
            else {
                nodePtr = head;
                prevPtr = nullptr;

                while (nodePtr != nullptr && nodePtr->value < newNode->value) {
                    prevPtr = nodePtr;
                    nodePtr = nodePtr->next;
                }
                if (prevPtr == nullptr) {
                    head = newNode;
                    newNode->next = nodePtr;
                }
                else {
                    prevPtr->next = newNode;
                    newNode->next = nodePtr;
                }

            }
            break;

        case 'p':

            cout << "printing ... \n";
            nodePtr = head;
            while (nodePtr != nullptr) {
                cout << "elem: " << nodePtr->value << endl;
                nodePtr = nodePtr->next;
            }
            break;

        case 'h':
            //FIX
            int findVal;
            cin >> findVal;


            nodePtr = head;
            while (nodePtr->value != findVal) {
                nodePtr = nodePtr->next;
            }
            nextNode = nodePtr->next;
            prevNode = nodePtr->prev;
            nextNode->prev = prevNode;
            prevNode->next = nextNode;
            delete(nodePtr);

            break;

        case 'q':

            cout << "quitting ... \n";
            nodePtr = head;
            while (nodePtr != nullptr) {
                nextNode = nodePtr->next;
                cout << "deleting ... " << nodePtr->value << endl;
                delete nodePtr;
                nodePtr = nextNode;
            }

            break;

        default:
            system("CLS");
            cout << "Invalid character -- Please try again!" << endl;
            break;
        }

    } while (ch != 'q');


    system("pause");
    return 0;
}

Upvotes: 0

Views: 684

Answers (2)

Phil1970
Phil1970

Reputation: 2623

Well in h case, if you enter a value that does not exist, you would try to use the object at null address.

Also, if you delete the first node (the head), it won't get updated so any other operation after that what can fails as you use a destroyed object and this is undefined behavior.

Upvotes: 0

The Dark
The Dark

Reputation: 8514

This line will fail:

prevNode = nodePtr->prev;
.....
prevNode->next = nextNode;

because you don't give prev a value when you insert a node. So prevNode will always be nullptr

Stepping through line by line in the debugger will help you find these type of bugs.

Upvotes: 1

Related Questions