C++链表头插操作触发Segmentation Fault问题求助
链表头插操作触发段错误的问题排查与解决
问题描述
用C++实现链表程序时,执行头插(push_front)操作后调用printList()会触发Segmentation Fault;但使用push_back()后再调用printList()却能正常运行,多次排查未找到原因。
原代码
#include<iostream> using namespace std; class Node { private: int data; Node* next; public: Node() { data = 0; next = NULL; } void setData(int data) { this->data = data; } int getData() { return data; } void setNextNode(Node* node) { this->next = node; } Node* getNextNode() { return next; } }; class LinkedList { private: Node Head_node; public: void createList(int n) { int x; cin >> x; Head_node.setData(x); n--; while (n) { cin >> x; push_back(x); n--; } } Node* lastNode() { Node* temp = &Head_node; while ( (*temp).getNextNode() != NULL) //while is not last node { temp = (*temp).getNextNode(); } return temp; } void push_back(int x) { Node* temp = lastNode(); //move to last node Node* a = new Node; // create a new node (*temp).setNextNode(a); //link new node to list (*a).setData(x); //set new node data } void push_front(int x) { Node* a = new Node; (*a).setData(x); Node join = Head_node; (*a).setNextNode(&join); this->Head_node = (*a); } void printList() { Node* temp = &Head_node; do { cout << (*temp).getData() << " "; temp = (*temp).getNextNode(); } while (temp != NULL); } }; int main() { int n; cin >> n; LinkedList list; list.createList(n); list.push_front(29); list.printList(); return 0; }
错误原因分析
- 局部变量内存非法访问:
push_front方法中,Node join = Head_node;创建了Head_node的局部拷贝,函数执行完毕后join会被销毁,内存被系统回收。但新节点a的next指针指向了这个已失效的内存地址,后续printList遍历链表时访问该地址,直接触发段错误。 - 链表头节点设计错误:
LinkedList类中Head_node是栈上的Node对象,而非指针类型。头插操作需要动态更换头节点,但栈对象无法被动态替换,this->Head_node = (*a);只是将堆节点的数据拷贝到栈对象中,不仅造成堆内存泄漏,还彻底打乱了链表的结构逻辑。
修正方案
核心修改:将头节点改为指针类型
把LinkedList类的私有成员Head_node改为Node*,支持动态更换头节点,同时修正所有相关方法的逻辑:
修正后的完整代码
#include<iostream> using namespace std; class Node { private: int data; Node* next; public: Node() { data = 0; next = NULL; } void setData(int data) { this->data = data; } int getData() { return data; } void setNextNode(Node* node) { this->next = node; } Node* getNextNode() { return next; } }; class LinkedList { private: Node* head; // 改为指针类型 public: // 构造函数初始化头指针为NULL LinkedList() : head(NULL) {} void createList(int n) { int x; cin >> x; head = new Node; head->setData(x); n--; while (n) { cin >> x; push_back(x); n--; } } Node* lastNode() { Node* temp = head; while (temp->getNextNode() != NULL) { temp = temp->getNextNode(); } return temp; } void push_back(int x) { // 处理空链表情况 if (head == NULL) { head = new Node; head->setData(x); return; } Node* temp = lastNode(); Node* a = new Node; temp->setNextNode(a); a->setData(x); } void push_front(int x) { Node* a = new Node; a->setData(x); a->setNextNode(head); // 新节点指向原头节点 head = a; // 更新头指针为新节点 } void printList() { Node* temp = head; // 用while循环避免空链表时的非法访问 while (temp != NULL) { cout << temp->getData() << " "; temp = temp->getNextNode(); } } }; int main() { int n; cin >> n; LinkedList list; list.createList(n); list.push_front(29); list.printList(); return 0; }
关键修改说明
- 头节点改为指针:
Node* head;支持动态创建和更换头节点,符合链表的动态特性。 - 修正头插逻辑:新节点的
next指向原头节点,再将头指针更新为新节点,保证链表结构正确。 - 空链表处理:
push_back中增加空链表判断,避免空指针访问。 - 遍历逻辑优化:
printList改用while循环,避免空链表时进入do-while的非法访问。
内容的提问来源于stack exchange,提问作者thanguyen165
相关产品推荐
相关产品推荐

