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