c - 在链表中,最后一个节点->下一个不为NULL,导致段错误

标签 c linked-list segmentation-fault undefined-behavior singly-linked-list

该函数向链表添加新元素,由于它试图访问不应该存在的节点的字段(名称),因此发生段错误。但是,添加的第一个节点有 ->next = NULL,所以我不确定为什么它会进入 while 循环

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

typedef struct node {
    char name[50];
    struct node *next;
} *list;

list head = NULL;   //global variable

void add (char *name) {   //push

    //check if it already exists
    list node = head;
    printf("\naddent \"%s\"\head->name (prev inserted): %s\n",name,head->name);

    printf("****while:\n");

    while(node != NULL){
        printf("node: %p\n",node);      
        printf("node->name: %s\n",node->name);
        if(strcmp(node->name,name) == 0)
            return;
        node = node->next;
    }

    list newNode = malloc(sizeof(list)); 
    strcpy(newNode->name, name);
    newNode->next = head;
    head = newNode;
}

int main(){
    char name[50];
    while(/*condition*/) {
        scanf("%s", name);
        add (name);
    }
    return 0;
}

输入:

nameOne
nameTwo
nameThree
nameFour

我添加了printf s进行调试,我发现最后一个node->next不是NULL(它应该是),而是仅适用于“nameFour”,因此在尝试访问node->name时会发生SEGFAULT。 提前致谢。

最佳答案

本声明

printf("\naddent \"%s\"\head->name (prev inserted): %s\n",name,head->name);

已经调用未定义的行为,因为最初head可以等于NULL。因此,您可能无法像 head->name 那样使用空指针访问结构的数据成员。

我认为此语句中使用的名称实体

list newNode = malloc(sizeof(entity)); 

是一个 typedef 名称,声明如下

typedef struct node entity;

更新问题中的代码后,变量 head 的声明应遵循结构的声明

typedef struct node {
    char name[50];
    struct node *next;
} *list;

list head = NULL;   //global variable

也在本次调用的格式字符串中

printf("\naddent \"%s\"\head->name (prev inserted): %s\n",name,head->name);
                       ^^

存在无效的转义符号。

这是一个可产生预期结果的演示程序。

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

typedef struct node {
    char name[50];
    struct node *next;
} *list;

list head = NULL;

typedef struct node entity;

void add( const char *name ) {   //push

    //check if it already exists
    list node = head;

    while(node != NULL){
        if(strcmp(node->name,name) == 0)
            return;
        node = node->next;
    }

    list newNode = malloc(sizeof(entity));  //create entity
    strcpy(newNode->name, name);
    newNode->next = head;
    head = newNode;
}


void output()
{
    for ( list current = head; current != NULL; current = current->next )
    {
        printf( "\"%s\" -> ", current->name );
    }
    puts( "NULL" );
}

int main(void) 
{
    const char *s[] = { "nameOne", "nameTwo", "nameThree", "nameFour" };
    const size_t N = sizeof( s ) / sizeof( *s );
    
    for ( size_t i = 0; i < N; i++ ) add( s[i] );
    
    output();
    
    return 0;
}

程序输出为

"nameFour" -> "nameThree" -> "nameTwo" -> "nameOne" -> NULL

关于c - 在链表中,最后一个节点->下一个不为NULL,导致段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57658385/

相关文章:

将文本文件中的字符串与C中的另一个列表进行比较

c - 链接列表错误(语言: C)

c - 添加节点到链表失败

C++二叉搜索树去除段错误

c - 如何从一个长字符串中扫描多个字符串并将其存储在一个char *word[20]中?

c - 尝试生成线性近似表。输出中的值不正确

C 编程 - 限制用户输入一定数量的字符

c - 将给定链表的反向存储到另一个链表中

c - 反转C中双链表的元素

objective-c - EXC_BAD_ACCESS (SIGSEGV) - KERN_INVALID_ADDRESS