【问题标题】:Why am I getting segmentation fault while implementing linked list?为什么在实现链表时会出现分段错误?
【发布时间】:2019-07-10 18:30:32
【问题描述】:

在这个函数中,我得到了分段错误。我认为这与内存分配有关。我犯了什么错误?

现在,如果我初始化 Node* a =NULL,我的头指针最终会为 NULL。

struct Node {
    int data;
    struct Node* next;
    Node(int x) {
        data = x;
        next = NULL;
    }
};

Node* addTwoLists(Node* first, Node* second) {
    // Code here
    Node *a;
    Node *head = a;
    int bor = 0;
    while(first->next && second->next) {
        int ans = first->data + second->data;
        a = new Node((ans%10)+bor);
        bor = ans/10;
        a=a->next;
        first = first->next;
        second = second->next;
    }
    return head;
}

【问题讨论】:

  • 您是否在调试器中单步执行您的程序,检查相关变量的值以及它们在每一步如何变化?如果没有,你应该这样做。调试是程序员必备的技能。
  • 旁注:不确定Node *head = a; 的行为方式是否如您所想。不过,这不是 100% 确定的。
  • @Chipster 检查是循环条件。
  • 另外,正如我认为 Stroustrup 所说,教师需要停止教授 C 并教授 C++
  • "我犯了什么错误?" - 手动实现一个链表,而不是使用标准的std::liststd::forward_list 类。

标签: c++ struct linked-list initialization singly-linked-list


【解决方案1】:
  1. a 未初始化。在分配值之前,您不得使用a
  2. 你永远不会再分配给head,所以它永远不会是其他任何东西。

【讨论】:

    【解决方案2】:

    不是分配,而是指针使用错了。

    它应该是这样的。此代码维护一个变量last,它是添加到列表中的最后一个节点。你需要这个变量,所以你可以在列表的末尾。你显然是想自己做,但逻辑错了。

    Node* addTwoLists(Node* first, Node* second) {
        Node *last = NULL;
        Node *head = NULL;
        int bor = 0;
        while(first->next && second->next) {
            int ans = first->data + second->data;
            Node* a = new Node((ans%10)+bor);
            if (head == NULL) {
                head = last = a; // first node, update head and end of list
            }
            else {
                last->next = a; // add a to the end of the list
                last = a;       // update the end of the list
            }
            bor = ans/10;
            first = first->next;
            second = second->next;
        }
        return head;
    }
    

    未经测试的代码。

    【讨论】:

      【解决方案3】:

      对于初学者来说,变量head 具有不确定的值,并且在函数中没有改变。

      Node *a;
      Node *head = a;
      

      改变变量a并不意味着改变表达式a->next的值。

      // ...
      a = new Node((ans%10)+bor);
      //...
      a=a->next;
      

      函数可以写成如下方式(无需测试)

      Node * addTwoLists( const Node *first, const Node *second ) 
      {
          const int Base = 10;
      
          Node *head = nullptr;
      
          int bor = 0;
      
          Node **current = &head;
      
          for ( ; first != nullptr && second != nullptr; first = first->next, second = second->next )
          { 
              int sum = first->data + second->data + bor;
              *current = new Node( sum % Base );
              bor = sum / Base;
              current = &( *current )->next;
          }
      
          if ( bor )
          {
              *current = new Node( bor );
          }
      
          return head;
      }
      

      这是一个演示程序

      #include <iostream>
      
      struct Node 
      {
          explicit Node( int data, Node *next = nullptr ) : data( data ), next( next )
          {
          }
      
          int data;
          Node *next;
      };
      
      void push_front( Node **head, int x )
      {
          *head = new Node( x, *head );
      }
      
      Node * addTwoLists( const Node *first, const Node *second ) 
      {
          const int Base = 10;
      
          Node *head = nullptr;
      
          int bor = 0;
      
          Node **current = &head;
      
          for ( ; first != nullptr && second != nullptr; first = first->next, second = second->next )
          { 
              int sum = first->data + second->data + bor;
              *current = new Node( sum % Base );
              bor = sum / Base;
              current = &( *current )->next;
          }
      
          if ( bor )
          {
              *current = new Node( bor );
          }
      
          return head;
      }
      
      std::ostream & display_list( const Node *head, std::ostream &os = std::cout )
      {
          for ( ; head != nullptr; head = head->next )
          {
              os << head->data << ' ';
          }
      
          return os;
      }
      
      int main()
      {
          const int N = 10;
          Node *list1 = nullptr;
          Node *list2 = nullptr;
      
          for ( int i = 1; i < N; i++ ) push_front( &list1, i );
          for ( int i = N; --i != 0; ) push_front( &list2, i );
      
          display_list( list1 ) << '\n';
          display_list( list2 ) << '\n';
      
          Node *list3 = addTwoLists( list1, list2 );
      
          display_list( list3 ) << '\n';
      }
      

      它的输出是

      9 8 7 6 5 4 3 2 1 
      1 2 3 4 5 6 7 8 9 
      0 1 1 1 1 1 1 1 1 1     
      

      【讨论】:

      • 两星代码!正确,但对于不懂普通指针的人来说可能有点棘手?
      • @john 我更喜欢三星级干邑。:)
      【解决方案4】:

      您可能会因为各种原因在这里遇到分段错误。

      1. 如果firstsecondNULL 那么你会得到分段错误。所以请确保如果这两个节点不是NULL
      2. 您没有初始化所以先初始化吧。

      如您所愿,head 变量应包含答案列表的起始节点,因此您需要在列表开始时分配节点。

      只需在a = new Node((ans%10)+bor);之后添加这一行

      if(head == NULL) head = a;
      

      【讨论】:

      • 1.其实我也是这么想的,但是错了。请参阅我关于原始问题的对话。
      • 我在你发表评论之前就开始写这篇文章了。这就是为什么我没有注意到它。
      • 有道理。
      猜你喜欢
      • 2011-10-11
      • 2020-09-30
      • 2011-04-23
      相关资源
      最近更新 更多