删除双向链表尾元素触发signal SIGSEGV segmentation fault的原因是什么
问题定位
- 核心问题1:
put函数头插新元素时,未修改原有首节点的prev指针指向新节点,导致除首节点外所有元素的prev指针始终为nullptr。当执行get操作从尾部删除元素时,dl.last->prev取到空值,后续操作访问dl.last->next触发空指针解引用段错误。 - 次要问题2:
get函数中声明buffer指针时执行了不必要的new操作,会产生内存泄漏:new申请的内存地址会被后续buffer = dl.last赋值覆盖,永远无法被释放。
解决方案
- 修正
put函数逻辑,头插新元素后,若原有链表非空,将原首节点的prev指向新的首节点 - 移除
get函数中buffer指针对应的无用new操作,直接用指针指向待删除节点即可
修正后的完整dlist.h代码
#include <iostream> #include <exception> struct DListElem { // 链表元素 int info; DListElem * prev; DListElem * next; }; struct DList{ // 存储链表首尾元素指针 DListElem * first; DListElem * last; }; void initializeDList(DList & dl){ // 将dl初始化为空链表 dl.first = nullptr; dl.last = nullptr; } void put(DList& dl, int val){ // 在链表头部插入值为val的新元素 DListElem* front_elem = new DListElem; front_elem->info = val; front_elem->prev = nullptr; front_elem->next = dl.first; // 新增逻辑:原有首节点非空时,prev指向新首节点 if (dl.first != nullptr) { dl.first->prev = front_elem; } dl.first = front_elem; if(dl.last==nullptr) dl.last=dl.first; } bool get(DList& dl, int& val){ /* 从链表尾部删除元素(可操作时),删除元素的值通过val参数返回,释放链表元素内存。返回值表示是否成功取出元素,空链表返回false,否则返回true。*/ if(dl.last==nullptr) return false; DListElem* buffer = dl.last; // 直接指向待删除节点,无需new val = dl.last->info; if (dl.first==dl.last){ // 链表仅有1个元素 dl.last = nullptr; dl.first = nullptr; } else{ dl.last = dl.last->prev; dl.last->next = nullptr; } delete buffer; return true; }
内容的提问来源于stack exchange,提问作者tokyo
相关产品推荐
相关产品推荐

