You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

链表添加学生的bool函数出现Segmentation Fault问题求助

链表学生插入函数的段错误问题排查

作业要求实现一个链表,并编写bool函数:将给定ID和姓名的学生添加至链表;若该ID的学生已存在则返回false,否则修改链表并返回true。目前代码运行出现Segmentation Fault,求帮助。

教授提供的结构体定义

struct snode{
  int id;
  char * name;
  struct snode * next;
};

struct slist{
 struct snode * front;
};

我实现的bool函数

bool insert_student(int id, char name[], struct slist * lst) {
    struct snode *head = malloc(sizeof(struct snode));
    head = lst->front;
    // check if list is empty
    if (head != NULL) {
        struct snode *node = malloc(sizeof(struct snode));
        while (node != NULL) {
            // traverse the list to see if student exists in list
            if (node->id = id) {
                return 0;
            }
            else {
                // if it doesnt exist, add it
                struct snode *ins_std = malloc(sizeof(struct snode));
                ins_std = node->next;
                ins_std->id = id;
                ins_std->name = name;
                ins_std->next = lst->front;
                lst->front = ins_std;
                 
                return 1;    
            }
                 
            node = node->next;    
        } 
     } // if list is empty
     else {
         head->next = NULL;
         head->name = name;
         head->id = id;
         return 1;
     }
}

主函数代码

int main() {
    struct slist *head = create_list();
    int id1 = 11001;
    int id2 = 11002;
    int id3 = 11003;
    int id4 = 11004;
    int id5 = 11005;
    char name1[] = "Dave";
    char name2[] = "Ali";
    char name3[] = "John";
    char name4[] = "Randall";
    char name5[] = "Kelly";

    assert(insert_student(id1, name1, head) == 1);
    insert_student(id2, name2, head);
    insert_student(id3, name3, head);
    insert_student(id4, name4, head);
    insert_student(id5, name5, head);
}

问题分析与修正

你的代码存在多个导致段错误和逻辑错误的问题,逐个拆解:

1. 空指针直接访问(核心段错误原因)

  • 函数开头struct snode *head = malloc(sizeof(struct snode));之后立刻head = lst->front;,不仅浪费了malloc的内存(内存泄漏),更关键的是:当链表为空时,lst->front是NULL,此时进入else分支,你直接对head->next、head->name赋值——这是对空指针的解引用操作,直接触发段错误。

2. 链表遍历逻辑完全错误

  • 当链表不为空时,你malloc了一个新的node,但这个node并没有指向链表的任何节点,里面的next和id都是随机垃圾值。直接进入while(node != NULL)循环并访问node->id,属于访问未初始化内存的未定义行为,极大概率触发段错误。
  • 正确的遍历应该从链表的头节点lst->front开始,而不是新malloc的节点。

3. 相等判断写成赋值操作

  • if (node->id = id)是赋值语句,不是相等比较,这会把传入的id赋值给node->id,然后永远返回true,导致只要进入循环就直接返回0,逻辑完全错误。应该改成if (node->id == id)。

4. 插入节点的逻辑错误

  • 你在遍历的第一个节点不匹配时就直接插入,没有遍历完整个链表检查ID是否存在,这会导致重复ID的学生被错误插入。
  • struct snode *ins_std = malloc(sizeof(struct snode));之后立刻ins_std = node->next;,再次浪费malloc的内存,而且如果node->next是NULL,后续对ins_std->id的赋值又是空指针解引用,触发段错误。

5. 字符串处理隐患

  • ins_std->name = name;直接把传入的字符数组地址赋值给指针,如果传入的是局部数组(比如主函数里的name1~name5),后续如果这些数组被销毁,链表中的name指针就会变成野指针。正确做法是用strdup(name)或者手动malloc内存后复制字符串。

修正后的代码

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

struct snode{
  int id;
  char * name;
  struct snode * next;
};

struct slist{
 struct snode * front;
};

// 补充create_list的实现,确保初始化front为NULL
struct slist* create_list() {
    struct slist* lst = malloc(sizeof(struct slist));
    lst->front = NULL;
    return lst;
}

bool insert_student(int id, char name[], struct slist * lst) {
    // 第一步:遍历链表检查ID是否已存在
    struct snode *current = lst->front;
    while (current != NULL) {
        if (current->id == id) {
            return false; // ID已存在,返回false
        }
        current = current->next;
    }

    // 第二步:ID不存在,创建新节点
    struct snode *new_node = malloc(sizeof(struct snode));
    if (new_node == NULL) {
        return false; // 内存分配失败
    }
    new_node->id = id;
    // 复制字符串,避免野指针
    new_node->name = strdup(name);
    if (new_node->name == NULL) {
        free(new_node);
        return false;
    }

    // 第三步:头插法插入新节点(也可以改为尾插,根据需求调整)
    new_node->next = lst->front;
    lst->front = new_node;

    return true;
}

int main() {
    struct slist *head = create_list();
    int id1 = 11001;
    int id2 = 11002;
    int id3 = 11003;
    int id4 = 11004;
    int id5 = 11005;
    char name1[] = "Dave";
    char name2[] = "Ali";
    char name3[] = "John";
    char name4[] = "Randall";
    char name5[] = "Kelly";

    assert(insert_student(id1, name1, head) == true);
    assert(insert_student(id2, name2, head) == true);
    assert(insert_student(id3, name3, head) == true);
    assert(insert_student(id4, name4, head) == true);
    assert(insert_student(id5, name5, head) == true);
    // 测试重复ID
    assert(insert_student(id1, name1, head) == false);

    // 可以添加链表打印函数验证结果
    return 0;
}

内容的提问来源于stack exchange,提问作者Ali Ghosn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 19:24:21