【问题标题】:Segmentation fault while implementing linkedlists in c++在 C++ 中实现链表时出现分段错误
【发布时间】:2020-09-30 14:45:15
【问题描述】:

我目前正在学习数据结构,我试图创建一个函数 insert 以在第 n 个位置插入一个节点,但我总是遇到分段错误,请您帮忙。

#include <iostream>
using namespace std;
struct node {
  int data;
  node* next;
};
struct node* head = NULL;
void insert(int dat, int pos) {
  node* temp = new node;
  temp->data = dat;
  temp->next = NULL;
  if (pos == 1) {
    temp->next = head;

    head = temp;
    return;
  }
  node* newtemp = head;
  for (int i = 0; i <= pos - 1; i++) {
    newtemp = newtemp->next;
  }
  temp->next = newtemp->next;
  newtemp->next = temp;
}
void print() {
  node* temp = head;
  while (temp != NULL) {
    cout << temp->data;
    temp = temp->next;
  }
  cout << endl;
}
int main() {
  head = NULL;
  insert(4, 1);
  insert(6, 2);
  print();
}

【问题讨论】:

  • 使用调试器逐步完成。如果您不知道如何在两行之间添加 std::cout 语句并通过最后一个打印语句的位置来解决问题,那么您就会知道问题出在哪里。尽可能添加空检查。我的猜测是任何时候人们实现一个位置或索引并使用它来遍历最有可能是问题的链接列表。您应该在 insert() 中使用 temp->next != nullptr 进行遍历
  • 阅读 good C++ programming 书籍和 C++ 编译器的文档。对于GCC,请参阅this,并阅读调试器的文档(例如GDB)。请参阅this reference 并阅读How to debug small programs

标签: c++ algorithm c++11 data-structures


【解决方案1】:

应该是

i<pos-1
temp->next=newtemp->next;
newtemp->next=temp;

你应该检查链表是否有你给的位置

即,如果您将第 6 位的节点添加到具有 2 个节点的链表中,则会出现分段错误。

按NULL->下一个

所以你应该检查链表的长度是否小于或等于位置。

    flag=false;
  while(temp!=NULL)
{
      if(i==Pos){
          flag=true;
          break;
      }
      temp=temp->next;
     i++;
}

如果 flag 为 false,则长度不足,否则在 temp 中做你的事情

【讨论】:

    【解决方案2】:

    insert()函数的这个语句:

      for (int i = 0; i <= pos - 1; i++) {
    

    对于插入元素6,您正在定位2

      First iteration:
    
      initialize i with 0
      0 <= 2 - 1 ==> true
    
      newtemp = newtemp->next
      [After this statement, newtemp is NULL because your linked list has only one element]
    
      i++  ==> i is now 1
    
      Second iteration
    
      1 <= 2 - 1  ===> true
    
      newtemp = newtemp->next
    
      [newtemp is NULL and this statment will attempt to access next of a NULL
       which is resulting in segmentation fault]
    

    希望你了解分段错误的原因,一个简单的改动就可以解决这个问题——添加NULL检查newtemp节点,像这样

      for (int i = 0; i < pos && newtemp->next != NULL; i++) {
    

    您的代码不会检查传递的pos 值的有效性,并且在您当前的实现中,如果pos 值大于链表的大小,它将在列表末尾添加元素。当pos 的值无效时,您可能想抛出错误。此外,您不会释放分配给链表节点的内存。遵循良好的编程习惯 - 在程序退出之前释放分配的内存。


    补充:

    由于您在 c++ 中实现链表,因此您应该在实现中使用面向对象的概念。例如将数据和函数捆绑在一个单元中对该数据进行操作:

    class Node {
    private: 
            int data; 
            Node* next;
    public: 
            // Add constructor for initialization of memeber variables
            // Add destructor for cleanup and release memory
            void insert(int dat, int pos);
            void print();
    };
    

    更好的实现方式是将节点和链表分开在两个不同的类中,并将它们的数据与各自的操作绑定。例如

    class Node {
    private:
            int data;
            Node* next;
    public:
            Node();
            Node(const int& val);
            void setData(const int& val);
            int getData() const;
            void setNext(Node* const nodePtr);
            Node* getNext() const;
    };
    

    Node对象组成的单链表类LinkedList

    class LinkedList {
    private:
            Node* headNode;
            Node* tailNode;
            Node* currNode;
            unsigned int count;
    public:
            LinkedList(); // constructor
            // other overload of constructor, copy constructor, assignment operator, move semantics ....
            ~LinkedList(); // destructor 
    
            bool insertNode(const Node& newNode);
            // other overload of insert, like insert at given position, at head of list, at tail of list etc..
    
            unsigned int getCount() const;
            Node* getHeadNode() const;
            Node* getCurrNode() const;
            Node* getTailNode() const;
    
            bool deleteNode(const Node& node);
            // other overload of delete node like detete tail node, delete head node etc.
    
            bool deleteList();
    };
    

    【讨论】:

      猜你喜欢
      • 2020-06-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-17
      • 2012-06-10
      • 1970-01-01
      • 1970-01-01
      • 2021-09-03
      • 1970-01-01
      相关资源
      最近更新 更多