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

C++栈类拷贝构造后触发Segmentation fault,析构函数问题求助

问题分析:栈类Segmentation Fault问题排查与解决

问题现象

运行测试代码后,程序输出正常内容后触发Segmentation fault:

#include <iostream>
#include <string>
#include "Stack.h"
using namespace std;

int main() 
{
    string Text;
    Stack S1;

    S1.push("Mary");
    S1.push("Apple");
    S1.push("Tom");
    S1.peek(Text);
    cout << "Results from peek: " << Text << endl;

    S1.view();
    cout << "Hello";
    
    Stack S2(S1);
}

程序输出:

Results from peek: Tom
TOP -> Tom -> Apple -> Mary -> BOTTOM
Segmentation fault

GDB调试信息:

Program received signal SIGSEGV, Segmentation fault.
__GI___libc_free (mem=0x55fa1e0ff3c3c990) at malloc.c:3102
3102    malloc.c: No such file or directory.

Valgrind检测结果(确认问题出在析构函数):

==1236== Conditional jump or move depends on uninitialised value(s)
==1236==    at 0x10983D: Stack::~Stack() (in my_folder)
==1236==    by 0x1094D1: main (in my_folder)
==1236==
==1236== Use of uninitialised value of size 8
==1236==    at 0x109846: Stack::~Stack() (in my_folder)
==1236==    by 0x1094D1: main (in my_folder)
==1236==

栈类定义及核心实现如下:

typedef std::string SElement;

class Stack {
        public:
            Stack();
            Stack( Stack & );
            ~Stack();
            void push ( const SElement );
            void pop( SElement & );
            void peek( SElement & );
            void view();
        private:
            struct SNode;
            typedef SNode * SNodePtr;
            struct SNode {
                SElement element;
                SNodePtr next;
            };
            SNodePtr top;
};
// 构造函数
Stack::Stack()
{
    top = nullptr;
}

// 析构函数
Stack::~Stack()
{
    SNodePtr nextNode;

    while (top != nullptr) {
        nextNode = top->next;
        delete top;
        top = nextNode;
    }
}

// push实现
void Stack::push( const SElement Text)
{
    SNodePtr NewNode = new SNode;
    
    NewNode->next = top;
    NewNode->element = Text;
    top = NewNode;
}

原因分析

问题根源在于拷贝构造函数未正确实现:

  • 你声明了拷贝构造函数Stack( Stack & );,但未提供具体逻辑,编译器会自动生成默认拷贝构造函数。默认拷贝是浅拷贝,只会直接复制top指针的地址值,不会复制整个链表节点。
  • 当执行Stack S2(S1);时,S2的top指针与S1的top指向同一块内存区域。
  • 程序结束时,S1和S2的析构函数会先后执行:第一个析构函数(如S2的)会释放整个链表的所有节点,此时S1的top变成悬空指针;第二个析构函数(S1的)访问悬空指针的next成员,触发未初始化值的访问,最终导致free操作时的Segmentation fault。

Valgrind的报错也验证了这一点:析构函数中使用了已失效的未初始化指针。

解决方法

实现深拷贝版本的拷贝构造函数,复制整个链表的所有节点,而非仅复制指针:

// 修改拷贝构造函数参数为const(拷贝不应修改原对象)
Stack::Stack(const Stack &other) {
    top = nullptr;
    if (other.top == nullptr) {
        return;
    }

    // 复制第一个节点
    SNodePtr currentOther = other.top;
    SNodePtr newNode = new SNode;
    newNode->element = currentOther->element;
    newNode->next = nullptr;
    top = newNode;
    SNodePtr currentThis = top;

    // 遍历原栈,复制剩余节点
    currentOther = currentOther->next;
    while (currentOther != nullptr) {
        SNodePtr temp = new SNode;
        temp->element = currentOther->element;
        temp->next = nullptr;
        currentThis->next = temp;
        currentThis = temp;
        currentOther = currentOther->next;
    }
}

同时,遵循C++的三/五法则,补充实现赋值运算符重载,避免后续赋值操作出现同样的浅拷贝问题:

Stack& Stack::operator=(const Stack& other) {
    // 防止自赋值
    if (this == &other) {
        return *this;
    }

    // 先释放当前栈的所有节点
    SNodePtr nextNode;
    while (top != nullptr) {
        nextNode = top->next;
        delete top;
        top = nextNode;
    }

    // 深拷贝原栈节点
    if (other.top == nullptr) {
        top = nullptr;
        return *this;
    }

    SNodePtr currentOther = other.top;
    SNodePtr newNode = new SNode;
    newNode->element = currentOther->element;
    newNode->next = nullptr;
    top = newNode;
    SNodePtr currentThis = top;

    currentOther = currentOther->next;
    while (currentOther != nullptr) {
        SNodePtr temp = new SNode;
        temp->element = currentOther->element;
        temp->next = nullptr;
        currentThis->next = temp;
        currentThis = temp;
        currentOther = currentOther->next;
    }

    return *this;
}

最后,记得同步修改类声明中的拷贝构造函数参数为const Stack&:

Stack(const Stack &);

内容的提问来源于stack exchange,提问作者cwjensen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 06:35:36