簡體   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