为什么 printf 会在链表中导致段错误?

Why does printf cause a segfault in a linked list?

我的代码接受一串由空格分隔的整数,并从中构建一个链表,-1 除外。为什么打印 nextNode -> data 会导致段错误?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct node Node;
struct node {
  int data;
  Node *next;
};

void build_linked_list(Node **head_ptr) {
  char *string = malloc(1028);
  char *p = string, *found = string;
  Node *nextNode = NULL;
  if (fgets(string, 1028, stdin) != NULL) {
    while ((found = strsep(&p, " \n")) != NULL) {
      if (strcmp(found, "-1") == 1) {
        Node *node = malloc(sizeof(Node));
        node->data = atoi(found);
        node->next = nextNode;
        nextNode = node;
      }
    }
  }
  *head_ptr = nextNode;
  printf("%i\n", nextNode->data); //error here
  free(string);
}

int main() {
  Node *head = NULL;
  build_linked_list(&head);
  return EXIT_SUCCESS;
}

你尝试在任何情况下打印 nextNode->data,但是如果 nextNodeNULL 怎么办?尝试访问无效指针的成员将导致分段错误。

详情:

  1. 你把指针初始化为NULL

    Node *nextNode = NULL;
    
  2. 你更新指针,但是只在特定条件下:

    if (fgets(string, 1028, stdin) != NULL) {
      while ((found = strsep(&p, " \n")) != NULL) {
        if (strcmp(found, "-1") == 1) {
          /* ... */
          nextNode = node;
        }
      }
    }
    
  3. 你打印字段

     printf("%i\n", nextNode->data); //error here
    

    但如果不满足条件,指针可能仍为NULL

要解决此问题,请在取消引用之前检查指针:

if( nextNode )
{
    printf("%i\n", nextNode->data);
}
else
{
    printf("NULL nextnode\n");
}

您在阅读 nextNode->data 之前没有检查是否 nextNode != NULL

strcmp(3) - Linux manual page

strcmp() returns an integer indicating the result of the comparison, as follows:

   · 0, if the s1 and s2 are equal;

   · a negative value if s1 is less than s2;

   · a positive value if s1 is greater than s2.

当两个字符串不同时从 strcmp() 返回的内容不一定是 1,因此 strcmp(found, "-1") == 1 是检查 found 是否不是 [=] 的错误表达式18=].

似乎 strcmp() 在您的环境中返回了 1 以外的东西,并且没有执行插入,因此 NULLnextNode->data 处取消引用,调用分段错误。

试试这个:

void build_linked_list(Node **head_ptr) {
  char *string = malloc(1028);
  char *p = string, *found = string;
  Node *nextNode = NULL;
  if (fgets(string, 1028, stdin) != NULL) {
    while ((found = strsep(&p, " \n")) != NULL) {
      /* use != 0 to check string inequility and avoid processing empty string */
      if (strcmp(found, "-1") != 0 && strcmp(found, "") != 0) {
        Node *node = malloc(sizeof(Node));
        node->data = atoi(found);
        node->next = nextNode;
        nextNode = node;
      }
    }
  }
  *head_ptr = nextNode;
  if (nextNode != NULL) { /* check if nextNode is not NULL */
    printf("%i\n", nextNode->data); //error here
  }
  free(string);
}