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

检查循环条件在'Add_End'功能,你觉得呢'current'将循环结束的时候?提示:它不会是最后一个节点。 –

+0

如果不是在'List'内部完全嵌套'Node','List'成为'Node'的一个朋友,这使得一些相当容易,为Node提供参数化构造函数(除非你能想到一个原因你会想提供一个'Node'和* not *来设置它的数据成员;我当然不能)。如果你在Xcode下进行调试,它将直接停止在有问题的行上(并显示过程中'current'的值为NULL) – WhozCraig

我设法纠正代码,所以我将解释我做了什么的情况下,别人遇到了同样的问题。

更改:在我解释修复之前,让我解释一下我所做的修改。链表的最后一个节点本身可以​​保存一个数据值,而不仅仅是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)是-112233455head->Next()(即,头节点的next)是NULL这种方法的缺点是不可能拥有包含整数-1122334455的单项清单,但我认为这个数字很可能不需要。只要列表中至少有两项,head->Data()可以是-1122334455


NEW CODE:代码的其余部分反映了这些修改。由于我只对List.cpp和Node.cpp进行了重大更改,因此我在下面仅复制了它们。其他三个程序文件基本不变。仅供参考,有很多冗余returnthis的,我没有打扰删除。

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