链表添加学生的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
相关产品推荐
相关产品推荐

