抛出C ++异常:读取访问冲突。这是nullptr

时间:2016-02-21 21:03:21

标签: c++

对于我的一个编程课程,我们需要设计一个程序,该程序可以通过我们的教师自己编写的“压力测试”来运行。

我们正在处理节点和链接列表,但其方式与我在该主题上查看过的任何YouTube视频都不同。

过去几天我一直在试着弄清楚我的计划有什么问题,但是我没有运气。

这是我的Node.cpp文件的代码(不包括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;
}

这是我的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;
    }
}

基本上,我已经自己测试了我的程序,并且我已经能够创建一个链表并运行我所有的添加和删除功能并打印出列表就好了。我的问题是我运行了我们的教师给我们的测试,它看起来就像我遇到问题一样(那些打印消息在另一个文件中,但他们似乎只是打印传递的字符串参数)< / p>

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; 

这进行了18次测试,但是我的程序永远不会“超过”第一次。它通过第一次测试然后突然抛出一个错误。

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

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

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

    return (isPassed);
}

我实际上在崩溃之前得到了这个输出

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

Test 1: size of empty list is zero: PASSED

所以它通过了第一次测试,但从来没有让它离开那里。我的意思是我试图在

周围投掷一条cout消息
score += test1() ? 2 : 0; 
std::cout << "Done with test 1"
score += test2() ? 2 : 0; 
score += test3() ? 3 : 0; 

但是从未输出过。相反,我的程序中断,Visual Studio弹出一条消息说

Exception thrown: read access violation.

this was nullptr.

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

然后它指向我在Node.cpp中的方法

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

很抱歉,我知道这很多文字需要通读,但现在我已经无法忍受了,我没有时间进入办公时间,因为它应该在明天早上到期。

编辑:我尝试省略第一个测试并运行它。它通过接下来的6次测试,但在第7次(第8次)失败时出现同样的错误。

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

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

    isPassed = !list.search(42);
    printPassFail(isPassed);
    return (isPassed); 
}

1 个答案:

答案 0 :(得分:8)

LinkedList析构函数有几个问题。首先,将m_size设置为0a设置为NULL是没有意义的,因为它们都会在析构函数的末尾消失。更重要的是,当列表为空时,代码将尝试取消引用空指针:

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

这是一种更清晰的写作方式:

Node* a = m_front;
while (a != NULL) {
    Node *temp = a->getNext();
    delete a;
    a = temp;
}