C语言char型双向链表运行报段错误valgrind检测内存仍可达求助
问题原因与修复方案
1. 段错误触发原因
- 空指针访问:
list_insert函数未做边界校验,直接访问pos.node->prev、before->next指针,当以下场景出现时直接触发非法内存访问:- 向空链表插入节点,此时
pos.node为NULL,解引用直接崩溃 - 向链表头部插入节点,此时
pos.node->prev为NULL,执行before->next = node时访问空指针
- 向空链表插入节点,此时
- 内存分配失败未处理:
make_node函数未校验malloc、strdup的返回值,分配失败返回NULL时后续解引用操作同样会触发段错误
2. valgrind内存泄漏原因
still reachable类型泄漏说明程序退出时仍有已分配的内存未被释放,且对应内存的指针还未丢失。你的代码只实现了节点创建逻辑,没有对应的节点销毁、链表清理逻辑:
- 节点的
value字段是strdup分配的堆内存,需要单独释放 - 节点本身是
malloc分配的,释放value后需要再释放节点结构体本身
程序退出前未遍历链表逐个释放所有节点的value和节点本身,就会触发该报错。
修复代码示例
修复后的make_node函数
static struct node *make_node(const char *value) { if (value == NULL) { return NULL; } struct node *result = malloc(sizeof(struct node)); if (result == NULL) { return NULL; } result->value = strdup(value); // strdup分配失败时先释放已申请的node,避免内存泄漏 if (result->value == NULL) { free(result); return NULL; } result->next = NULL; result->prev = NULL; return result; }
修复后的list_insert函数
ListPos list_insert(ListPos pos, const char *value) { struct node *node = make_node(value); if (node == NULL) { return pos; } // 处理空链表插入场景 if (pos.node == NULL) { pos.node = node; return pos; } struct node *before = pos.node->prev; struct node *after = pos.node; node->next = after; after->prev = node; node->prev = before; // 非头插场景才修改前驱节点的next指针 if (before != NULL) { before->next = node; } // 若插入位置为链表头,需额外更新链表结构体的头指针,根据你自行定义的List结构补充对应逻辑即可 pos.node = node; return pos; }
补充节点销毁逻辑
void free_node(struct node *node) { if (node == NULL) { return; } free(node->value); free(node); }
程序退出前遍历整个链表,逐个调用free_node释放所有节点即可解决valgrind的内存泄漏报错。
内容的提问来源于stack exchange,提问作者user17441147
相关产品推荐
相关产品推荐

