C++:试图向链表添加新节点产生“线程1:EXC_BAD_ACCESS(code = 1,address = 0x0)”错误
我正在编写一个创建和操作链表的作业分配程序。我遇到了Node.cpp中的Node :: SetData函数以及List.cpp中的List :: Add_End(特别是“current-> SetData(data);”)行中的“EXC_BAD_ACCESS”错误和由于某种原因(特别是“//将Add_End节点添加到列表中”)在main.cpp中行。我假设一旦Node :: SetData错误得到解决,这些其他错误将自行解决。C++:试图向链表添加新节点产生“线程1:EXC_BAD_ACCESS(code = 1,address = 0x0)”错误
通过堆栈溢出和谷歌搜索后,我无法确定为什么会发生此错误。我认为这个问题(New to C++, "EXC_BAD_ACCESS" error I don't understand)会有帮助,但我仍然有问题。
我做了哪些编码错误?
的main.cpp
#include <iostream>
#include <cstddef>
using namespace std;
#include "List.h"
int main()
{
// New list
List list;
Node *answer;
// Add_End nodes to the list
list.Add_End(111);
list.Print();
list.Add_End(222);
list.Print();
list.Add_End(333);
list.Print();
list.Add_End(444);
list.Print();
list.Add_End(555);
list.Print();
// Delete nodes from the list
list.Delete(444);
list.Print();
list.Delete(333);
list.Print();
list.Delete(222);
list.Print();
list.Delete(555);
list.Print();
list.Delete(111);
list.Print();
cout << "Testing Add_Front: and others" << endl;
list.Add_Front(888);
list.Print();
list.Add_Front(999);
list.Print();
list.Add_Front(49);
list.Print();
cout << "Checking find function" << endl;
answer = list.Find(888);
cout << "Value for node returned by find function call with 888 is " << answer->Data() << "." << endl;
cout << "Checking find function" << endl;
answer = list.Find(999);
cout << "Value for node returned by find function call with 888 is " << answer->Data() << "." << endl;
cout << "Checking find function" << endl;
answer = list.Find(49);
cout << "Value for node returned by find function call with 888 is " << answer->Data() << "." << endl;
cout << "Call find function with value not in list." << endl;
answer = list.Find(7);
if (answer == NULL)
{
cout << "returned null pointer since 7 not found" << endl;
}
else
{
cout << "in else of answer == NULL where Value for node returned by find function call with 7 is " << answer->Data() << "." << endl;
}
cout << "testing delete_front: " << endl;
list.Delete_Front();
list.Print();
cout << "testing delete_end: " << endl;
list.Delete_End();
list.Print();
return 0;
}
List.h
#ifndef LIST_H
#define LIST_H
#include <cstddef>
#include "Node.h"
class List
{
private:
Node* head;
public:
List();
void Add_End(int data);
void Delete(int data);
void Delete_Front();
void Add_Front(int data);
void Delete_End();
Node* Find(int data);
void Print();
};
#endif
List.cpp
#include <iostream>
#include <cstddef>
using namespace std;
#include "List.h"
List::List()
{
head = NULL;
return;
}
void List::Add_End(int data)
{
Node* current;
Node* newEnd = new Node();
for (current = head; current != NULL; current = current->Next())
{}
current->SetData(data);
current->SetNext(newEnd);
newEnd->SetData(NULL);
newEnd->SetNext(NULL);
return;
}
void List::Delete(int data) {
/*
FILL IN CODE (will do later)
*/
return;
}
void List::Delete_Front()
{
/*
FILL IN CODE (will do later)
*/
return;
}
void List::Add_Front(int data)
{
Node* newNode = new Node();
newNode->SetData(data);
newNode->SetNext(head);
head = newNode;
return;
}
void List::Delete_End()
{
if (head == NULL)
{
cout << "List has no member so cannot delete end" << endl;
return;
}
// check if one in length
if (head->Next() == NULL)
{
head = NULL;
return;
}
// 2 or greater in length
Node* current;
Node* prev;
prev = head;
for (current = head->Next(); current->Next() != NULL; current = current->Next())
{
prev = current;
}
prev->SetNext(NULL);
return;
}
Node* List::Find(int data)
{
Node* current;
for (current = head; current != NULL && current->Data() != data; current = current->Next())
{}
if(current == NULL)
{
cout << "Did not find " << data << "." << endl;
return NULL;
}
else // found
{
cout << "Found " << data << "." << endl;
return current;
}
}
void List::Print()
{
Node* current;
for (current = head; current != NULL; current = current->Next())
{
cout << current->Data() << " ";
}
cout << endl;
return;
}
Node.h
#ifndef NODE_H
#define NODE_H
class Node
{
private:
int data;
Node* next;
public:
Node();
void SetData(int aData);
void SetNext(Node* aNext);
int Data();
Node* Next();
};
#endif
Node.cpp
#include <cstddef>
#include "Node.h"
Node::Node()
{
this->SetData(NULL);
this->SetNext(NULL);
return;
}
void Node::SetData(int aData)
{
this->data = aData;
return;
}
void Node::SetNext(Node* aNext)
{
this->next = aNext;
return;
}
int Node::Data()
{
return data;
}
Node* Node::Next()
{
return next;
}
我设法纠正代码,所以我将解释我做了什么的情况下,别人遇到了同样的问题。
更改:在我解释修复之前,让我解释一下我所做的修改。链表的最后一个节点本身可以保存一个数据值,而不仅仅是NULL
(即最后一个节点的data
不需要是NULL
,但它的next
应该是NULL
),所以我认为这会更好。代码在每个重要位置都反映了这一点,如List::Add_End(int data)
函数。
THE FIX:我修改了List
构造函数来创建列表中的头节点。所以,即使列表是空的,链表也总是会有至少一个节点。我将解释程序是如何在后面的空列表和非空列表之间识别的。
这里原来的构造函数:
List::List()
{
head = NULL;
return;
}
这是新构造:
List::List()
{
Node* headNode = new Node();
head = headNode;
return;
}
为什么会做出这样的修改?据我所知,我遇到了EXC_BAD_ACCESS错误,因为List::Add_End(int data)
函数试图操作链接列表的head
就好像它是一个节点对象,实际上它不是。 (我相信这是marom在回答这个问题时的意思)。这就是为什么我改变了编码,使得列表总是包含头节点,即使列表为空。
区分空列表和非空列表。我修改了Node
构造函数,将data
设置为整数-1122334455
,而不是像我最初那样的NULL
。因此,如果列表是空的,则head->Data()
(即,头节点的data
)是-112233455
和head->Next()
(即,头节点的next
)是NULL
。 这种方法的缺点是不可能拥有包含整数-1122334455
的单项清单,但我认为这个数字很可能不需要。只要列表中至少有两项,head->Data()
可以是-1122334455
。
NEW CODE:代码的其余部分反映了这些修改。由于我只对List.cpp和Node.cpp进行了重大更改,因此我在下面仅复制了它们。其他三个程序文件基本不变。仅供参考,有很多冗余return
和this
的,我没有打扰删除。
List.cpp
#include <iostream>
#include <cstddef>
using namespace std;
#include "List.h"
// -1122334455 is an arbitrary integer that is likely to never be needed by the user
List::List()
{
Node* headNode = new Node();
head = headNode;
return;
}
Node* List::Add_End(int data)
{
// if list is empty (i.e., list has only head node with data == -1122334455 & next == NULL)
if (head->Data() == -1122334455 && head->Next() == NULL)
{
head->SetData(data);
return head;
}
// if list is nonempty
else
{
Node* current;
Node* newEnd = new Node();
for (current = head; current->Next() != NULL; current = current->Next())
{}
current->SetNext(newEnd);
newEnd->SetData(data);
newEnd->SetNext(NULL);
return newEnd;
}
}
void List::Delete(int data)
{
Node* prev;
Node* current;
// if list is empty
if (head->Data() == -1122334455 && head->Next() == NULL)
{
cout << "Cannot delete this datum because list is empty." << endl;
return;
}
// if list contains 1 element
if (head->Data() == data && head->Next() == NULL)
{
head->SetData(-1122334455);
return;
}
else if (head->Data() != data && head->Next() == NULL)
{
cout << "Datum not found in list." << endl;
return;
}
// if list contains 2 or more elements
prev = head;
for (current = head->Next(); current->Data() != data && current->Next() != NULL; current = current->Next())
{
prev = prev->Next();
}
if (current->Data() == data && current->Next() != NULL)
{
prev->SetNext(current->Next());
delete current;
return;
}
else if (current->Data() == data && current->Next() == NULL)
{
prev->SetNext(NULL);
delete current;
return;
}
else
{
cout << "Datum not found in list." << endl;
return;
}
}
void List::Delete_Front()
{
Node* origHead = head;
Node* newHead = head->Next();
head = newHead;
delete origHead;
return;
}
void List::Add_Front(int data)
{
// if list is empty
if (head->Data() == -1122334455 && head->Next() == NULL)
{
head->SetData(data);
return;
}
// if list is nonempty
Node* newNode = new Node();
newNode->SetData(data);
newNode->SetNext(head);
head = newNode;
return;
}
void List::Delete_End()
{
if (head->Data() == -1122334455 && head->Next() == NULL)
{
cout << "List has no member so cannot delete end" << endl;
return;
}
// check if one in length
else if (head->Data() != -1122334455 && head->Next() == NULL)
{
head->SetData(-1122334455);
return;
}
// 2 or greater in length
else
{
Node* current;
Node* prev;
prev = head;
for (current = head->Next(); current->Next() != NULL; current = current->Next())
{
prev = current;
}
prev->SetNext(NULL);
return;
}
}
Node* List::Find(int data)
{
Node* current;
for (current = head; current != NULL && current->Data() != data; current = current->Next())
{}
if (current == NULL)
{
cout << "Did not find " << data << "." << endl;
return NULL;
}
else // found
{
cout << "Found " << data << "." << endl;
return current;
}
}
void List::Print()
{
if (head->Data() == -1122334455 && head->Next() == NULL)
{
cout << "List is empty." << endl;
return;
}
Node* current;
for (current = head; current != NULL; current = current->Next())
{
cout << current->Data() << " ";
}
cout << endl;
return;
}
Node.cpp
#include <cstddef>
#include "Node.h"
Node::Node()
{
// -1122334455 is an arbitrary integer that is likely to never be needed by the user
this->SetData(-1122334455);
this->SetNext(NULL);
return;
}
void Node::SetData(int aData)
{
this->data = aData;
return;
}
void Node::SetNext(Node* aNext)
{
this->next = aNext;
return;
}
int Node::Data()
{
return this->data;
}
Node* Node::Next()
{
return this->next;
}
在呼吁电流 - > SetData的首次(见下文)当前为NULL,所以你访问时获取页面错误(页面错误是错误现代操作系统给你,如果你尝试访问未分配的内存。在的Wndows该术语通常是访问冲突。)
void List::Add_End(int data)
{
Node* current;
Node* newEnd = new Node();
for (current = head; current != NULL; current = current->Next())
{}
current->SetData(data);
current->SetNext(newEnd);
newEnd->SetData(NULL);
newEnd->SetNext(NULL);
return;
}
检查循环条件在'Add_End'功能,你觉得呢'current'将循环结束的时候?提示:它不会是最后一个节点。 –
如果不是在'List'内部完全嵌套'Node','List'成为'Node'的一个朋友,这使得一些相当容易,为Node提供参数化构造函数(除非你能想到一个原因你会想提供一个'Node'和* not *来设置它的数据成员;我当然不能)。如果你在Xcode下进行调试,它将直接停止在有问题的行上(并显示过程中'current'的值为NULL) – WhozCraig