Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Exception thrown: read access violation. this was nullptr

Tags:

c++

For one of my programming classes, we are required to design a program that can be ran through the provided "stress tests" that our instructor wrote himself.

We are working with nodes and linked lists but in a way that is different than any of the YouTube videos I have looked at on the subject.

I've been tearing my hair out for the past couple of days trying to figure out what is wrong with my program but I'm having no luck.

Here is the code for my Node.cpp file (didn't include Node.h)

#include "Node.h"

Node::Node() {
    m_value = 0;
    m_next = nullptr;
}

void Node::setValue(int val) {
    m_value = val;
}

int Node::getValue() const {
    return m_value;
}

void Node::setNext(Node* prev) {
    m_next = prev;
}

Node* Node::getNext() const {
    return m_next;
}

Here is my LinkedList.cpp

#include <iostream>
#include <vector>
#include "LinkedList.h"

LinkedList::LinkedList() {
    m_front = nullptr;
    m_size = 0;
}

LinkedList::~LinkedList() {
    // Deconstructor
    m_size = 0;
    Node* a = m_front;
    Node* b = a->getNext();
    while (a->getNext() != NULL) {
        delete a;
        a = b;
        b = b->getNext();
    }
    delete a;
    a = NULL;
}

bool LinkedList::isEmpty() const{
    if (m_size == 0) {
        return true;
    }
    else {
        return false;
    }
}

int LinkedList::size() const {
    return m_size;
}

bool LinkedList::search(int value) const {
    if (m_size == 0) {
        return false;
    }
    else if (m_size == 1) {
        if (m_front->getValue() == value) {
            return true;
        }
        else {
            return false;
        }
    }
    else {
        Node* a = m_front;

        for (int i = 0; i < m_size; i++) {
            if (a->getValue() == value) {
                return true;
            }
            else {
                a = a->getNext();
            }
        }
        return false;
    }
}

void LinkedList::printList() const {
    std::cout << "List: ";
    if (m_size == 0) {
        // Print Nothing
    }
    else if (m_size == 1) {
        std::cout << m_front->getValue();
    } 
    else {
        Node* a = new Node();
        a = m_front;
        int b = m_front->getValue();
        std::cout << b << ", ";

        while (a->getNext() != NULL) {
            a = a->getNext();

            if (a->getNext() == NULL) {
                std::cout << a->getValue();
            }
            else {
                std::cout << a->getValue() << ", ";
            }
        }
    }
    std::cout << std::endl;

}

void LinkedList::addBack(int value) {
    Node* a = new Node();
    a->setValue(value);
    if (m_size == 0) {
        m_front = a;
    }
    else {
        Node* b = new Node();
        b = m_front;
        while (b->getNext() != NULL) {
            b = b->getNext();
        }
        b->setNext(a);
    }
    m_size++;
}

void LinkedList::addFront(int value) {
    Node* a = new Node(); // Check later

    a->setNext(m_front);
    a->setValue(value);
    m_front = a;
    m_size++;

}

bool LinkedList::removeBack() {
    if (m_size == 0) {
        return false;
    }
    else {
        Node* a = new Node();
        Node* b = new Node();
        a = m_front;
        while (a->getNext() != NULL) {
            b = a;
            a = a->getNext();
        }
        b->setNext(nullptr);
        delete a;
        a = NULL;
        m_size--;
        return true;
    }
}

bool LinkedList::removeFront() {
    if (m_size == 0) {
        return false;
    }
    else {
        Node* a = new Node();
        a = m_front;
        m_front = m_front->getNext();
        delete a;
        a = NULL;
        m_size--;
        return true;
    }
}
std::vector<int> LinkedList::toVector() const {
    if (m_size == 0) {
        std::vector<int> b;
        return b;
    }
    else {
        std::vector<int> a(m_size);
        Node* b = new Node();
        b = m_front;
        for (int i = 0; i < m_size; i++) {
            a[i] = b->getValue();
            b = b->getNext();
        }
        return a;
    }
}

Basically, I've tested my program on my own and I've been able to make a linked list and run all my add and remove functions and print out the lists just fine. My problem is I run the test that our instructor gave us and it looks like this at the point where I'm having problems (Those print messages are in another file but all they seem to do is print the string arguments that are passed)

int score = 0;
const int MAX_SCORE = 90;

std::cerr << "\n\n=========================\n";
std::cerr << "   RUNNING TEST SUITE    \n";
std::cerr << "=========================\n\n";

//Run test and award points where appropriate
score += test1() ? 2 : 0; 
score += test2() ? 2 : 0; 
score += test3() ? 3 : 0; 

This goes on for 18 tests, but my program never "makes" it past the first one. It passes the first test then all of a sudden throws an error.

bool Test_LinkedList::test1()
{
    LinkedList list;
    bool isPassed = false;

    printTestMessage("size of empty list is zero"); 

    isPassed = list.size() == 0;
    printPassFail(isPassed);

    return (isPassed);
}

I actually get this output before it crashes

=========================
   RUNNING TEST SUITE
=========================

Test 1: size of empty list is zero: PASSED

So it passes the first test but never makes it out of there. What I mean is that I have tried throwing in a cout message around

score += test1() ? 2 : 0; 
std::cout << "Done with test 1"
score += test2() ? 2 : 0; 
score += test3() ? 3 : 0; 

But that is never outputted. Instead my program breaks and Visual Studio pops up with a message saying

Exception thrown: read access violation.

this was nullptr.

If there is a handler for this exception, the program may be safely continued.

Then it points me to my method in Node.cpp that is

Node* Node::getNext() const {
    return m_next;
}

Sorry, I know this is a lot of text to read through but right now I'm beyond stumped and there is no time for me to go into office hours as it is due early tomorrow morning.

edit: i tried omitting the first test and running it. It gets through the next 6 tests but then fails on the 7th (8th) with the same exact error.

bool Test_LinkedList::test8()
{
    LinkedList list;
    bool isPassed = false;

    printTestMessage("search returns false on empty list");

    isPassed = !list.search(42);
    printPassFail(isPassed);
    return (isPassed); 
}
like image 576
Damian Vu Avatar asked Feb 21 '16 21:02

Damian Vu


1 Answers

The LinkedList destructor has a couple of problems. First, it's pointless to set m_size to 0 and a to NULL since they will both go away at the end of the destructor. More important, the code will attempt to dereference a null pointer when the list is empty:

Node* a = m_front; // okay, gets that head pointer
Node* b = a->getNext(); // bang!!

Here's a cleaner way to write it:

Node* a = m_front;
while (a != NULL) {
    Node *temp = a->getNext();
    delete a;
    a = temp;
}
like image 56
Pete Becker Avatar answered Nov 18 '22 16:11

Pete Becker