[英]C++: Attempting to add new node to linked list yields “Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)” error
I'm writing a program for a homework assignment that creates and manipulates a linked list. 我正在编写一个用于作业的程序,该程序可以创建和操作链表。 I am encountering an "EXC_BAD_ACCESS" error with the Node::SetData function in Node.cpp, as well as with a line in List::Add_End in List.cpp (specifically "current->SetData(data);") and a line in main.cpp for some reason (specifically "// Add_End nodes to the list").
我在Node.cpp的Node :: SetData函数以及List.cpp的List :: Add_End行(特别是“ current-> SetData(data);”)中遇到一行“ EXC_BAD_ACCESS”错误,并且由于某种原因,main.cpp中的行(特别是“ // Add_End节点到列表”)。 I assume that once the Node::SetData error is fixed, these other errors will resolve themselves.
我假设一旦修复了Node :: SetData错误,这些其他错误将自行解决。
After searching through Stack Overflow and Google, I cannot determine why this error is occurring. 在搜索Stack Overflow和Google之后,我无法确定为什么会发生此错误。 I thought this question ( New to C++, "EXC_BAD_ACCESS" error I don't understand ) would help, but I'm still having issues.
我认为这个问题( C ++的新功能,我不理解的“ EXC_BAD_ACCESS”错误 )会有所帮助,但是我仍然遇到问题。
What coding error(s) have I made? 我犯了什么编码错误?
main.cpp 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 清单.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 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 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;
}
While calling current->SetData for the first time (see below) current is NULL and so you get page fault when accessing it (page fault is the error modern OSes give you if you try to access unallocated memory. Under wndows the term usually is Access violation.) 第一次调用current-> SetData时(请参见下文),current为NULL,因此在访问它时会出现页面错误(页面错误是现代操作系统在尝试访问未分配的内存时给您的错误。访问冲突。)
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;
}
I managed to correct the code, so I'll explain what I did in case someone else encounters the same problem. 我设法更正了代码,因此在其他人遇到相同问题的情况下,我将做些解释。
ALTERATION: Before I explain the fix, let me explain a change I made. 变更:在我解释此修复程序之前,让我解释一下我所做的更改。 The last node of the linked list can hold a data value itself, not just
NULL
(ie, the last node's data
does not need to be NULL
, but its next
should be NULL
), so I thought this would be better. 链表的最后一个节点本身可以保存数据值,而不仅仅是
NULL
(即,最后一个节点的data
不必为NULL
,而其next
应该为NULL
),所以我认为这样会更好。 The code reflects this in every location where it matters, such as the List::Add_End(int data)
function. 该代码在涉及的每个位置都反映了这一点,例如
List::Add_End(int data)
函数。
THE FIX: I modified the List
constructor to create a head node for the list. 解决方法:我修改了
List
构造函数以为列表创建头节点。 So, the linked list will always have at least one node, even if the list is empty. 因此,即使列表为空,链接列表也将始终至少具有一个节点。 I will explain how the program discerns between empty and nonempty lists later.
稍后,我将说明程序如何识别空列表和非空列表。
Here is the original constructor: 这是原始的构造函数:
List::List()
{
head = NULL;
return;
}
Here is the new constructor: 这是新的构造函数:
List::List()
{
Node* headNode = new Node();
head = headNode;
return;
}
Why make this modification? 为什么要进行此修改? As far as I can tell, I encountered the EXC_BAD_ACCESS error because the
List::Add_End(int data)
function tried to manipulate the linked list's head
as if it were a node object, when actually it was not. 据我所知,我遇到了EXC_BAD_ACCESS错误,因为
List::Add_End(int data)
函数试图操纵链接列表的head
,就好像它是节点对象一样,而实际上并非如此。 (I believe this is what marom meant in his answer to this question.) This is why I altered the coding such that the list always contains a head node, even when the list is empty. (我相信这是他回答这个问题的意思。)这就是为什么我更改了编码,使得即使列表为空,列表也始终包含头节点。
Discerning between empty and nonempty lists. 区分空列表和非空列表。 I altered the
Node
constructor to set data
to the integer -1122334455
, instead of NULL
like I originally did. 我更改了
Node
构造函数以将data
设置为整数-1122334455
,而不是像我最初那样将其设置为NULL
。 So, if the list is empty, then head->Data()
(ie, the head node's data
) is -112233455
and head->Next()
(ie, the head node's next
) is NULL
. 因此,如果列表为空,则
head->Data()
(即头节点的data
)为-112233455
而head->Next()
(即头节点的next
)为NULL
。 The downside to this approach is that it's impossible to have a one-item list containing the integer -1122334455
, but I figure this number is likely to be unneeded. 这种方法的缺点是不可能有一个包含整数
-1122334455
的单项列表 ,但是我认为这个数字很可能是不必要的。 As long as the list has at least two items, head->Data()
can be -1122334455
. 只要列表中至少包含两项,
head->Data()
可以为-1122334455
。
NEW CODE: The rest of the code reflects these modifications. 新代码:其余代码反映了这些修改。 Since I only made significant changes to List.cpp and Node.cpp, I have reproduced only them below.
由于我仅对List.cpp和Node.cpp进行了重大更改,因此下面仅复制了它们。 The other three program files are essentially unchanged.
其他三个程序文件基本上未更改。 FYI, there are many redundant
return
's and this
's that I didn't bother to delete. 仅供参考,有很多多余的
return
, this
是我不想删除的。
List.cpp 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 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;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.