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

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;
}

错误原因分析

  1. 局部变量内存非法访问:push_front方法中,Node join = Head_node;创建了Head_node的局部拷贝,函数执行完毕后join会被销毁,内存被系统回收。但新节点a的next指针指向了这个已失效的内存地址,后续printList遍历链表时访问该地址,直接触发段错误。
  2. 链表头节点设计错误: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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 22:27:19