C编程使用链表时出现段错误和错误输出

C programming segmentation fault error and wrong outputs when using linked list

我一直在尝试在 C 中使用简单的链表,但是我得到了错误的输出,然后是分段错误。

这个程序的目的是从一个文本文件中获取 3 个参数,并将它们作为一个对象放在链表中。每次读取新行时,都会使用 newData 方法将其放入列表中,并最终使用 display 方法将其显示到控制台。

然而,当我尝试这样做时,我只输出添加到链表的最后一项,并且 它显示了我的文本文件中存在的行数,然后是分段错误,我无法理解为什么。

如果有人知道这个问题或如何解决它,我们将不胜感激。代码如下所示。

main.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "param.h"
#include "function.h"
#include "lists.h"

int main(int argc, char *argv[])
{
char *p1;
int p2;
int p3;
FILE *in;
char *temp;
char param[100];


in = fopen(argv[1],"r");
while (fgets(param,100,in) != NULL) {
    temp = strdup(param);
    p1 = strsep(&temp,",");
    p2 = atoi(strsep(&temp,","));
    p3 = atoi(strsep(&temp,","));

    newData(p1,p2,p3);
    free(temp);
}

fclose(in);
display();
return 0;
}

lists.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "param.h"
#include "function.h"
#include "lists.h"

static struct node*head;
static struct parameters tempTaskObject;
static int status = 1;

void newData(char * p1, int p2, int p3){
if (status == 1)
{
    head = (struct node*)malloc(sizeof(struct node));
}

tempTaskObject.p1 = p1;
tempTaskObject.p2 = p2;
tempTaskObject.p3 = p3; 

insert(&head,&tempTaskObject);
status = 0;
}

void display(){
traverse(head);
}

function.c:

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

#include "function.h"
#include "param.h"

void insert(struct node **head, Parameters *newParameters) {
struct node *newNode = malloc(sizeof(struct node));

newNode->parameters = newParameters;
newNode->next = *head;
*head = newNode;

}


void traverse(struct node *head) {
struct node *temp;
temp = head;

while (temp != NULL) {
    printf("[%s] [%d] [%d]\n",temp->parameters->p1, temp->parameters->p2, temp->parameters->p3);
    temp = temp->next;
}
}

param.h:

#ifndef TASK_H
#define TASK_H

typedef struct parameters {
char *p1;
int p2;
int p3;
} Parameters;

#endif

lists.h:

#define MIN_PRIORITY 1
#define MAX_PRIORITY 10

void newData(char *p1, int p2, int p3);
void display();

function.h:

#include "param.h"

struct node {
Parameters * parameters;
struct node *next;
};

void insert(struct node **head, Parameters * parameters);
void traverse(struct node *head);

[测试输入 1]:

P1, 1, 11
P2, 2, 22
P3, 3, 33
P4, 4, 44
P5, 5, 55
P6, 6, 66
P7, 7, 77
P8, 8, 88

[测试输出 1]:

P8, 8, 88
P8, 8, 88
P8, 8, 88
P8, 8, 88
P8, 8, 88
P8, 8, 88
P8, 8, 88
P8, 8, 88
Segmentation fault (core dumped)

[测试输入 2]:

P1, 1, 11
P2, 2, 22
P3, 3, 33

[测试输出 2]:

P3, 3, 33
P3, 3, 33
P3, 3, 33
Segmentation fault (core dumped)

对于这个 while 循环中的初学者

while (fgets(param,100,in) != NULL) {
    temp = strdup(param);
    p1 = strsep(&temp,",");
    p2 = atoi(strsep(&temp,","));
    p3 = atoi(strsep(&temp,","));

    newData(p1,p2,p3);
    free(temp);
}

免费的呼唤

free(temp);

没有效果,因为 temp 将等于 NULL。

另一方面,函数 newData 也可以调用未定义的行为,因为它在第一次调用时使用 struct node 类型的未初始化对象,将其传递给函数 insert。

if (status == 1)
{
    head = (struct node*)malloc(sizeof(struct node));
}

而且你总是在这个初始化语句中使用指向同一个全局对象的指针static struct parameters tempTaskObject;

newNode->parameters = newParameters;

请注意,当函数依赖于大量全局变量时,以这种方式定义函数是个坏主意。