【问题标题】:Linked list shows segmentation fault error链表显示分段错误错误
【发布时间】:2020-07-17 01:33:09
【问题描述】:

我对 C 和指针还很陌生。

以下代码用于实现一个链表,其中每个节点都包含一个记录数据。

但是,当我编译并运行该程序时,它显示错误“分段错误”,我猜我的代码中的以下部分会出错。
head->next = NULL 在 list.c 中的函数
我怀疑由于取消引用空指针而发生分段错误错误,但不知道我的代码有什么问题。

列表.h

#ifndef LIST_H
#define LIST_H
#include <stddef.h>
#include "record.h"

typedef struct node node;

struct node {         
  record  data;           
  node   *next;             
};

typedef node *record_list;  /* a record list is represented by its "head"
                               pointer */

void list_init(record_list *plist);

int list_insert(record_list *plist, const record *prec);

void list_clear(record_list *plist);

void list_print(const record_list *plist);
#endif

io.h

#ifndef IO_H
#define IO_H
#include "record.h"

void print_record(const record *p);

int read_record(record *p);

/* reads a string from stdin */
int get_word(const char prompt[], char word[]);

/* reads an int from stdin */
int get_int(const char prompt[], int *p);
#endif

记录.h

#ifndef RECORD_H
#define RECORD_H

#define IDSIZE    10
#define NAMESIZE  20

typedef struct {          
  char   last[NAMESIZE];   
  char   first[NAMESIZE];  
} name;

typedef struct {   
  char  id[IDSIZE]; 
  name  name;      
  int   score;  
} record;
#endif

list.c

#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "record.h"
#include "list.h"
#include "io.h"

/* initializes a record list (specified via plist) to an empty list */
void list_init(record_list *plist) {
  node *head;
  head = *plist;
  head = NULL;
  head->next = NULL;
  printf("%s", "segmentation???\n");
}

/*
 * inserts a record (specified via prec) into a record list
 */
int list_insert(record_list *plist, const record *prec) {
  node *current, *temp;
  printf("%s", "list insert\n");
  current = *plist;
  while (current->next != NULL) {
    current = current->next;
  }
  temp = (node *)malloc(sizeof(node));
  if (temp == NULL) {
    fprintf(stderr, "memory allocate failed");
    return 0;
  }
  current->next = temp;
  current->next->data = *prec;
  current->next->next = NULL;

  printf("%s", "list insert done\n");
  return 1;
}

/*
 * deallocates all dynamic memory associated with a record list (specified
 * via plist) & resets the record list to an empty list
 */
void list_clear(record_list *plist) {
  printf("%s", "list clear\n");
  free((*plist)->next);
  plist = NULL;
  (*plist)->next = NULL;
}

/* prints all records in a record list (specified via plist) */
void list_print(const record_list *plist) {
  node *current;
  current = *plist;
  printf("%s", "list print\n");
  while (current->next != NULL) {
    print_record(&(current->data));
    current = current->next;
  }
}

io.c

#include <stdio.h>
#include <string.h>
#include "record.h"
#include "io.h"
#define LINESIZE 1024

/*
 * prints a record (specified via p);
 */
void print_record(const record *p) {
  printf("%d %s %s %s\n", p->score, p->name.last, p->name.first, p->id);
}

/*
 * reads a record from stadard input & stores it via p;
 */
int read_record(record *p) {
  return (
        get_word("Enter id: ", p->id)
    &&  get_word("Enter last name: ", p->name.last)
    &&  get_word("Enter first name: ", p->name.first)
    &&  get_int("Enter score: ", &(p->score))
  );
}

/* reads a string from stdin */
int get_word(const char prompt[], char word[]){
  char line[LINESIZE];
  char temp[LINESIZE];
  while (1) {
    printf("%s", prompt);
    if(!fgets(line, LINESIZE, stdin)){
      clearerr(stdin);
      return 0;
    }
    if (sscanf(line, "%s", temp) == 1){
      strcpy(word, temp);
      return 1;
    }
  }
}

/* reads an int from stdin */
int get_int(const char prompt[], int *p) {
  char line[LINESIZE];
  while (1) {
    printf("%s", prompt);
    if (!fgets(line, LINESIZE, stdin)) {
      clearerr(stdin);
      return 0;
    }
    if (sscanf(line, "%d", p) == 1) {
      return 1;
    } else {
      printf("%s", "Error: The input is not given in integer.\n");
    }
  }
}

main.c

#include <stdio.h>
#include "record.h"
#include "list.h"
#include "io.h"


int main(void) {
  record_list  list;
  record       r;

  printf("address of list: %ld\n", &list);
  printf("address of list: %ld\n", &(list->next));
  list_init(&list);

  while (read_record(&r)) {
    printf("%s\n", "read success");
    if (!list_insert(&list, &r))
      break;
  }

  list_print(&list);
  return 0;
}

【问题讨论】:

  • 你是在调试器下运行的吗(例如gdb)。使用-g 编译。然后执行:gdb ./myprogram。然后输入rungdb 将捕获段错误。然后,您可以键入bt 以获取堆栈回溯,您将看到出现错误的代码行。另请查看 gdb 中的 frame。您也可以使用s 单步执行程序
  • “我怀疑由于取消引用空指针而发生分段错误错误”。你不需要怀疑或猜测。调试代码。使用调试器甚至基本的调试打印语句来跟踪程序执行。调试器可以准确地告诉您哪一行代码段错误以及变量值是什么。 How to debug small programs
  • 好的。我将尝试使用 gdb 进行调试,然后更新我的状态:)
  • 天哪,我不知道有这么方便的 C 调试器。顺便说一句,它说“程序收到信号 SIGSEGV,分段错误”。并且错误出现在while (current-&gt;next != NULL) 中的list_insert() 函数中。
  • 所有您的代码作为单个代码块发布可能对[对我们和有帮助。您可以在顶部插入 [missing] .h 文件。这样,我们可以下载单个文件,编译它[您发布的内容应该干净地编译],然后运行它[可能在上面使用gdb]。在您的特定情况下,它不应该是太多 [更多] 代码。

标签: c pointers linked-list segmentation-fault


【解决方案1】:

如果您的目标是创建一个空列表并且 plist 是指向列表头部的指针,您必须使用 *plist = NULL;plist 指向的变量设置为 NULL ,您可以摆脱代码导致分段错误

好的,我想我找到了下一个错误:

current = *plist;
while (current->next != NULL) {
    current = current->next;
}

会导致错误,因为你第一次调用 list_insert 你有 *plist 等于 NULL 因为列表是空的,所以 current->next != NULL 会导致错误(current 也等于 NULL)

我建议如下:

printf("%s", "list insert\n");

if (*plist == NULL) {
    temp = (node * )malloc(sizeof(node));
    if (temp == NULL) {
        fprintf(stderr, "memory allocate failed");
        return 0;
    }
    plist = temp;
    (*plist) ->data = *prec;
    (*plist) ->next = NULL;
    return 1;
}

current = *plist;
while (current->next != NULL) {
    current = current->next;
}

其余代码原样,我为 *pilist 等于 NULL 的情况添加了一个 if,在这种情况下 temp 将指向第一个元素并且必须分配给 plist

【讨论】:

  • 我之前尝试过,但仍然导致分段错误。
  • 等等,所以实际上我删除了导致错误的代码并按照您所说的输入*plist = NULL,但现在它导致我的list_insert()函数出错。我认为访问current-&gt;next 有问题。
  • 谢谢@Tommimon!您的解决方案解决了分段错误问题。感谢您的友好回复:)
  • 如果你不知道它是如何工作的,我建议你仔细阅读What should I do when someone answers my question?部分
猜你喜欢
  • 1970-01-01
  • 2018-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多