[英]Unhandled exception thrown: read access violation. x was 0x20B4112
[英]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
把成員變量變成了一個陷阱。 它需要是checkNodeExsits
和addNodeAfter
的局部變量,以防止這些函數破壞使用它們的函數的 state。 這導致質疑mypointer
是否應該是它所在的任何地方的成員變量。 這導致對temp
、 nextnode
和prevnode
感到疑惑。 他們聽起來都像是本地 state 信息的臨時持有者。 可能唯一應該成為成員的DoubleLinkedList
成員是head
。
要修復:從 class 中刪除mypointer
的定義並解決由此產生的編譯器錯誤。 如果mypointer
的使用可以很容易地替換為局部變量,那么就這樣做。 對於任何剩余的並且需要長期存儲以供重新使用的東西,您必須更有創意。 調用 scope 需要多長的生命周期和多長的寬度才能獲得所需的行為,然后為這個新變量賦予一個適當的描述性名稱,以幫助您記住應該使用它的環境。
我建議對除head
之外的其他成員變量重復此過程,其中必要的 scope 和生命周期是顯而易見的。
一般經驗法則:使變量 scope 盡可能緊湊。 只有在以后絕對需要重用變量的 state 時才加寬變量的 scope ,並且如果發現必須非常小心以確保不會導致意外的副作用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.