簡體   English   中英

拋出未處理的異常:讀取訪問沖突。 “this”是 0x8 - 使用 Shared_ptr

[英]Unhandled exception thrown: read access violation. "this" was 0x8 - Using Shared_ptr

Node.h

#pragma once
#include <iostream>
#include<memory>


class Node
{
public:
    Node();
    Node(int k, int d);
    int key;
    int data;

    
    std::shared_ptr<Node> next;
    std::shared_ptr<Node> previous;
    //Node* next;
    //Node* previous;
};

doubleLinkedList.h

#pragma once

/*! \class Double Linked List
    \brief A double linked list data structure
*/

#include <iostream>
#include "../Node.h"
#include <string>
#include<memory>



class DoubleLinkedList : public Node
{
private :
    std::shared_ptr<Node> head;             //Node* head; 
    std::shared_ptr<Node> temp;           //Node* temp;
    std::shared_ptr<Node> mypointer;            //Node* ptr;
    std::shared_ptr<Node> nextNode;
    std::shared_ptr<Node> prevNode;

public :
    DoubleLinkedList();
    DoubleLinkedList(std::shared_ptr<Node> n);
    std::shared_ptr<Node> checkNodeExsits(int k); //Node*
    void addNodeToFront(std::shared_ptr<Node> n); //Node*
    void addNodeToEnd(std::shared_ptr<Node>  n);   //Node*
    void addNodeAfter(int k, std::shared_ptr<Node> n); //Node*
    void UpdateNode(int k , int d);
    void deleteNode(int k);
    void printList();
    void printInfo(std::string Info);



};

Node.cpp

#include "Node.h"
#include <iostream>



Node::Node() 
{
    key = 0;
    data = 0;
    next = nullptr;
    previous = nullptr;
}


Node::Node(int k, int d) 
{
    key = k;
    data = d;
}

doubleLinkedList.cpp

#include <iostream>
#include "include\doubleLinkedList.h"



DoubleLinkedList::DoubleLinkedList()
{
    head = nullptr;
}


DoubleLinkedList::DoubleLinkedList(std::shared_ptr<Node> n)
{
  
     head = n;
}

std::shared_ptr<Node> DoubleLinkedList::checkNodeExsits(int k)
{
     temp = nullptr;
     mypointer = head;

    while (mypointer != nullptr) {
        if (mypointer -> key == k) {
            temp = mypointer;
        }
        
        mypointer = mypointer-> next;

    }

    return temp;
}


void DoubleLinkedList::addNodeToFront(std::shared_ptr<Node> n)
{
    if (checkNodeExsits(n->key) != nullptr) 
    {
        
        printInfo("Node Already exist with key Number ");
    }
    else {
        if (head == nullptr) {
            head = n;
            printInfo("Node Added as Head Node");
        }
        else {
            head->previous = n;
            n->next = head;
            head = n;
            printInfo("Node Added To The Begining");
        }

    }
}


void DoubleLinkedList::addNodeToEnd(std::shared_ptr<Node> n)
{

    if (checkNodeExsits(n->key) != nullptr) 
    {
        printInfo("Node Already exist with key Number");
    }
    else {
        if (head == nullptr) 
        {
            head = n;  // if there isnt any node in the list.
            printInfo("Node Has Been Added As Head Node");
        }
        else {
            mypointer = head;
            while (mypointer ->next != nullptr)
            {
                mypointer = mypointer->next;
            }
            mypointer->next = n;
            n->previous = mypointer;
            printInfo("Node Has Been Added To The End");
        }
    }

}


void DoubleLinkedList::addNodeAfter(int k, std::shared_ptr<Node> n)
{
    mypointer = checkNodeExsits(k);
    if (mypointer == nullptr) {
        printInfo("No Node Exists With The Key Value");
    }
    else {
        if (checkNodeExsits(n -> key) != nullptr) {
            printInfo("Node Already exist with key Number");
        }
        else {
               nextNode = mypointer-> next;
            // inserting at the end
            if (nextNode == nullptr) {
                mypointer-> next = n;
                n -> previous = mypointer;
                printInfo("Node Inserted at the END");
            }

            //inserting in between
            else {
                n -> next = nextNode;
                nextNode -> previous = n;
                n -> previous = mypointer;
                mypointer-> next = n;
                printInfo("Node Inserted in Between");

            }

        }
    }
}


void DoubleLinkedList::UpdateNode(int k, int d)
{
    mypointer = checkNodeExsits(k);
    if (mypointer != nullptr) {
        mypointer-> data = d;
        std::cout << "Node Data Updated Successfully" << std::endl;
    }
    else {
        std::cout << "Node Doesn't exist with key value : " << k << std::endl;
    }
}


void DoubleLinkedList::deleteNode(int k)
{
    mypointer = checkNodeExsits(k);
    if (mypointer == nullptr) {
        std::cout << "No node exists with key value: " << k << std::endl;
    }
    else {

        if (head -> key == k) {
            head = head -> next;
            std::cout << "Node UNLINKED with keys value : " << k << std::endl;
        }
        else {
             nextNode = mypointer-> next;
             prevNode = mypointer-> previous;
            // deleting at the end
            if (nextNode == nullptr) {

                prevNode -> next = nullptr;
                std::cout << "Node Deleted at the END" << std::endl;
            }

            //deleting in between
            else {
                prevNode -> next = nextNode;
                nextNode -> previous = prevNode;
                std::cout << "Node Deleted in Between" << std::endl;

            }
        }
    }
}


void DoubleLinkedList::printList()
{
    if (head == nullptr) {
        std::cout << "No Nodes in Doubly Linked List";
    }
    else {
        std::cout << std::endl << "Doubly Linked List Values : ";
         temp = head;

        while (temp != nullptr) {
            std::cout << "[Key: " << temp->key << ", Data: " << temp->data << "] <___> " << std::endl;
            temp = temp -> next;
        }
    }
}


void DoubleLinkedList::printInfo(std::string Info)
{
    std::cout << Info << std::endl;
}

main.cpp

#include <iostream>
#include "../include/doubleLinkedList.h"
#include"../Node.h"

void Print(std::string info)
{
    std::cout << info << std::endl;
}

int main() {

    DoubleLinkedList myNode;
    //Node* newNode = new Node(2,7);
    std::shared_ptr<Node> newNode = std::make_shared<Node>(2, 7); // enter key number and data number
    std::shared_ptr<Node> newNode1 = std::make_shared<Node>(3, 9);// enter key number and data number

    newNode->key;
    newNode->data;
    myNode.addNodeToFront(newNode);


    newNode->key;
    newNode->data;
    myNode.addNodeAfter(2, newNode1); // enter the key number of existing node and then to add new key number and new data
    myNode.printList();

   

    system("pause");
    return 0;
}

我得到的錯誤是:

unhandled exception thrown: read access violation. "this" was 0x8
To elaborate -
( Access violation reading location 0x0000000000000010. Unhandled exception thrown: read access violation).

所以,當我使用原始指針時,代碼會起作用。 我唯一可以從中推斷出的是,在void DoubleLinkedList::addNodeAfter() nextNode = mypointer-> next;的方法中有一個共享指針鏈。

或者不能為共享指針分配nullptr

我不知道為什么會這樣。

讓我們來addNodeAfter

mypointer = checkNodeExsits(k);

我們已經檢查以確保值k存在於列表中,如果存在則獲取指向它的指針。 如果沒有,我們會得到一個 null 指針。

    if (mypointer == nullptr) {

測試是否找到k 假設是, mypointer不是 null,我們輸入 else

    else {
        if (checkNodeExsits(n -> key) != nullptr) {

在這里,我們檢查以確保我們插入的節點不是重復的。 讓我們再次選擇else分支

        else {
               nextNode = mypointer-> next;

應該安全吧? 我們知道mypointer不是 null 因為我們之前測試過它。 但是當我們看...神聖的藍精靈! 程序崩潰了! 本來null,怎么變成null了?

答案在於另一個問題: mypointer是從哪里來的? 它沒有在這個function中定義,所以它有更寬的scope。原來它是一個DoubleLinkedList成員變量。 是不是有人在搞事情? 我們沒有多線程,所以它必須是 addNodeAfter 調用的另一個addNodeAfter

那必須是checkNodeExsits ,所以讓我們看一下。

std::shared_ptr<Node> DoubleLinkedList::checkNodeExsits(int k)
{
     temp = nullptr;
     mypointer = head; // well lookie here!

    while (mypointer != nullptr) {
        if (mypointer -> key == k) {
            temp = mypointer;
        }

        mypointer = mypointer-> next; // and here!

    }

    return temp;
}

我們可以看到,如果插入的節點的值不存在,那么就讓我們在else的情況下回到addNodeAfter我們要插入新節點的地方, mypointer只能為null!

mypointer 過於寬泛的mypointer把成員變量變成了一個陷阱。 它需要是checkNodeExsitsaddNodeAfter的局部變量,以防止這些函數破壞使用它們的函數的 state。 這導致質疑mypointer是否應該是它所在的任何地方的成員變量。 這導致對tempnextnodeprevnode感到疑惑。 他們聽起來都像是本地 state 信息的臨時持有者。 可能唯一應該成為成員的DoubleLinkedList成員是head

要修復:從 class 中刪除mypointer的定義並解決由此產生的編譯器錯誤。 如果mypointer的使用可以很容易地替換為局部變量,那么就這樣做。 對於任何剩余的並且需要長期存儲以供重新使用的東西,您必須更有創意。 調用 scope 需要多長的生命周期和多長的寬度才能獲得所需的行為,然后為這個新變量賦予一個適當的描述性名稱,以幫助您記住應該使用它的環境。

我建議對除head之外的其他成員變量重復此過程,其中必要的 scope 和生命周期是顯而易見的。

一般經驗法則:使變量 scope 盡可能緊湊。 只有在以后絕對需要重用變量的 state 時才加寬變量的 scope ,並且如果發現必須非常小心以確保不會導致意外的副作用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM