繁体   English   中英

C ++“访问冲突读取位置”错误

[英]C++ “Access violation reading location” Error

我刚刚实现了一个析构函数,并且得到了“访问冲突读取位置”。 我相信问题出在我的while循环中,但无法解决。

下面是我的代码。 如果需要引用列表类的其他任何部分,请告诉我。

谢谢!

List::List():first(NULL), last(NULL), nodeListTotal(0)
{
}    

List::~List()
{
    Node* currentNode = first;

    while( currentNode != 0 ) 
    {
        Node* temp = currentNode->getNext();
        delete currentNode;
        currentNode = temp;
    }

    first = 0;
}

这是我的整个List类。 我进行了建议的更改,删除了first = 0; 并将0更改为nullptr

#include "Node.h"
#include <string>
using namespace std;

class List
{
    private:
        int nodeListTotal;
        Node* first;
        Node* last;

    public:
        //Constructor
        List();
        //Destructor
        ~List();
        //Copy-Constructor
        //List(const List& theList);
        //////Overloading Assignment Operator
        //List& operator=(const List& L);

        void push_back(Node*);
        void push_front(Node*);
        Node* pop_back();
        Node* pop_front();
        Node* getFirst() const;
        Node* getLast() const;
        int getListLength() const;
};

List::List():first(NULL), last(NULL), nodeListTotal(0)
{
}

// Destructor
List::~List()
{
    Node* currentNode = first;

    while( currentNode != nullptr ) 
    {
        Node* temp = currentNode->getNext();
        delete currentNode;
        currentNode = temp;
    }
}

// Copy-Constructor
//List::List(const List& theList)
//{
//  Node * tempPtr = new Node;
//  tempPtr = theList.first;
//  List(tempPtr);
//  
//  while (tempPtr != NULL)
//  {
//      Node * copyNode = new Node;
//      copyNode = tempPtr;
//      tempPtr = tempPtr->getNext();
//      nodeListTotal++;
//  }
//}

// Overloading Assignemnt Operator
//List& List::operator=(const List& L)
//{
//  List* overList;
//  Node* temp = L.first;
//  
//  while( temp != NULL ) {
//      overList->getLast();
//      temp = temp -> getNext();
//      
//      return *this;
//}

void List::push_back(Node* newNode)
{
    Node* temp = last;
    if (temp)
        temp->setNext(newNode);
    else
        first = newNode;

    last = newNode;
    nodeListTotal++; 
}

void List::push_front(Node* newNode)
{
    Node* temp = getFirst();
    newNode->setNext(temp);
    first = newNode;
    nodeListTotal++;

    if (!temp)
        last = first;
}

Node* List::pop_back()
{
    Node* old = last;
    if (first == last)
    {
        first = 0;
        last = 0;
    }
    else
    {
        Node* temp = first;

        for (int i = 0; i < (nodeListTotal - 1); i++)
        {
            temp = temp->getNext();
        }

        temp->setNext(NULL);

        last = temp;
    }

        nodeListTotal--;
        return old;
}

Node* List::pop_front()
{
    Node* temp = getFirst();
    first = temp->getNext();

    if (!first)
        last = 0;

    nodeListTotal--;

    return temp;
}

Node* List::getFirst() const
{
    return first;
}

Node* List::getLast() const
{
    return last;
}

int List::getListLength() const
{
    return nodeListTotal;
}

Node.h

#include <string>
using namespace std;

class Node
{
    private:
        string dataItem;
        string dataUnit;
        int unitTotal;
        Node* next;

    public:
        //Constructor
        Node();

        Node(int, string, string);

        string getDescription( )const; 
        void setDescription(string);

        string getQuantityName()const; 
        void setQuantityName(string);

        int getQuantityNumber()const; 
        void setQuantityNumber(int);

        Node* getNext( )const; 
        void setNext(Node*);
};

Node::Node(void):dataItem("None"), dataUnit("None"), unitTotal(0), next(NULL)
{
}

Node::Node(int q, string i, string u):dataItem(i), dataUnit(u), unitTotal(q), next(NULL)
{
}

string Node::getDescription( ) const
{
    return dataItem;
}

void Node::setDescription(string iSetter)
{
    dataItem = iSetter;
}

string Node::getQuantityName() const
{
    return dataUnit;
}

void Node::setQuantityName(string uSetter)
{
    dataUnit = uSetter;
}

int Node::getQuantityNumber() const
{
    return unitTotal;
}

void Node::setQuantityNumber(int tSetter)
{
    unitTotal = tSetter;
}

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

void Node::setNext(Node* nSetter)
{
    next = nSetter;
}

Driver.cpp

int main( )
{
    //===============================================
    // PART ONE
    //===============================================
    cout << "\nPart I: push_front and pop_front\n";
    cout << "\n----------------------------------\n";
    List groceries;

    // test push_back function
    groceries.push_front(new Node(1, "gallon", "milk") );
    groceries.push_front(new Node(2, "loaves", "bread") );
    groceries.push_front(new Node(1, "dozen", "eggs" ) );
    groceries.push_front(new Node(1,  "package", "bacon") );

    cout << "\nThe original nodes in the List:\n";
    printList(groceries);
    cout << "\n----------------------------------\n";

    // test push_front function
    cout << "\nAdding to the front of the List:\n";
    cout << "\n----------------------------------\n";
    groceries.push_front(new Node(2, "lbs", "hamburger") );
    groceries.push_front(new Node(1, "dozen", "hamburger buns") );

    printList(groceries);
    cout << "\n----------------------------------\n";

    // test pop-front
    cout << "\nRemoving the first node from the list.\n";
    cout << "\n----------------------------------\n";
    Node* item = groceries.pop_front( );
    cout << "\nPopped " << item->getDescription( ) << " from the list.\n\n";
    printList(groceries);
    if (item != NULL)
        delete item;

    // ===============================================
    // PART TWO: Uncomment this block to test part two
    // ===============================================

    cout << "\n----------------------------------\n";
    cout << "\nPart Two: Push_back and pop_back";

    // test push_back
    groceries.push_back(new Node(2, "cans", "orange juice") );
    groceries.push_back(new Node(1, "lb", "swiss cheese") );

    cout << "\nAdding two nodes at the end\n";
    cout << "\n----------------------------------\n";
    printList(groceries);

    // test pop-back
    cout << "\n----------------------------------\n";
    cout << "\nRemove last node from the list\n";
    cout << "\n----------------------------------\n";
    item = groceries.pop_back( );
    cout << "\nPopped " << item->getDescription( ) << " from the list.\n\n";

    printList(groceries);
    if (item != NULL)
        delete item;
    // ============================================
    // end of part two
    // ============================================

    // ================================================
    // PART THREE: uncomment this block to test part three
    // ================================================
    /*
    // create a second list to test assignment
    cout << "\n\n--------------extra credit------------------\n";
    cout << "\n\n overloaded assignment operator\n";
    cout << "The hardware list ...\n";
    cout << "\n-------------------------------------------\n";
    List hardware;
    hardware.push_back(new Node(2, "lbs", "nails") );
    hardware.push_back( new Node(3, "gals", "white paint") );
    hardware.push_back(new Node(1, "piece", "plywood") );
    printList(hardware);
    hardware = groceries;
    cout << "\n-------------------------------------------\n";
    cout << "\nafter assignment";
    cout << "\n-------------------------------------------\n";
    printList(hardware);

    cout << "\n-------------------------------------------\n";
    cout << "\nTest the copy constructor\n";
    cout << "\n-------------------------------------------\n";
    printFirstNode(hardware);

    // ==============================================
    // end of part 3
    // ==============================================
    */
    cout << "\n-------------------------------------------\n";
    cout << "\nEnd of Test";
    cout << "\n-------------------------------------------\n";
    system("PAUSE");
    return 0;
}

看起来pop back不会从列表中删除最后一个节点,而是将其返回。 然后删除该节点,并在列表的析构函数中尝试再次删除该节点。

push_back()方法可能是您的罪魁祸首,加上未能将Node:next初始化为零。 如果仅使用push_back将一个节点添加到列表中,则该节点的下一个成员的值将是未知的,并且在析构函数中尝试删除引用随机内存位置的第二个节点将导致访问错误。 请确保已初始化节点值,或者如果将node.next是添加到列表中的第一个节点,则确保在push_back()中显式设置了node.next。

关于pop_back()和pop_front()的注意事项。 在空列表上调用pop_back()仍会减少nodeListTotal。 在空列表上调用pop_front()实际上会导致尝试访问地址0的访问冲突。

deletion中清理节点时,节点的以下deletion导致了问题。

if (item != NULL)
    delete item;

当您执行pop_back您要删除main()那个(最后一个)节点,但是在那之前的那个节点会发生什么呢? 它指向的是您删除的那个,并且未设置为NULL

因此,在析构函数中,当您开始删除节点时,您正在检查节点的NULL值。 一切正常,但是现在对于next未将其设置为NULL ,而是仍然指向您刚刚删除的那个。 因此,尝试释放已经释放的节点。

然后您的代码崩溃。

每当释放后续节点时,将前一个节点的nextNULL

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM