C++:尝试将新节点添加到链表会产生"线程 1:EXC_BAD_ACCESS(代码 = 1,地址 = 0x0)"错误

C++: Attempting to add new node to linked list yields "Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)" error

本文关键字:错误 EXC BAD 线程 ACCESS 地址 代码 0x0 新节点 节点 添加      更新时间:2023-10-16

我正在编写一个程序,用于创建和操纵链接列表的家庭作业。我正在遇到node.cpp中的node :: setData函数的" exc_bad_access"错误,以及list :: add_end in list.cpp中的行:: add_end(特别是" current-> setData(data);")和一个出于某种原因,在main.cpp中行(特别是"//add_end节点到列表")。我认为一旦node :: setData错误已修复,这些其他错误就会自行解决。

通过堆栈溢出和Google搜索后,我无法确定为什么会发生此错误。我认为这个问题(新的C ," exc_bad_access"我不理解的错误)会有所帮助,但我仍然有问题。

我犯了什么编码错误?

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;
}

首次调用current-> setData(请参见下文)电流为null,因此访问它时您会得到页面故障(页面故障是现代OS的错误,如果您尝试尝试,请给您要访问未分配的内存。在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;
}

我设法纠正了代码,所以我会解释我所做的,以防其他人遇到同样的问题。

更改:在解释修复程序之前,让我解释一下我所做的更改。链接列表的最后一个节点可以保存数据值本身,而不仅仅是NULL(即,最后一个节点的data不需要是NULL,而且其next应该是NULL),所以我认为这会更好。该代码在重要的每个位置都反映了这一点,例如List::Add_End(int data)函数。


修复程序:我修改了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()(即,Head Node的data)为-112233455head->Next()(即,Head Node的next)是NULL这种方法的不利之处在于,不可能拥有包含整数-1122334455的一个项目列表,但我认为这个数字可能不需要。只要列表至少有两个项目,head->Data()可以是-1122334455


新代码:代码的其余部分反映了这些修改。由于我只对list.cpp和node.cpp进行了重大更改,因此我仅在下面重现它们。其他三个程序文件本质上是没有变化的。仅供参考,有许多冗余的return'S和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;
    }