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

调用std::vector的push_back时触发Segmentation Fault求助排查

段错误原因分析与解决方案:CRTP基类构造中调用派生类方法访问未初始化成员

问题根源

C++对象的构造顺序是先基类、后派生类成员、最后派生类构造函数。你的代码中存在致命逻辑错误:

  1. 创建DerivedEngine对象时,首先执行基类AbstractEngine的构造函数
  2. 基类构造函数里直接调用了on_init,而CRTP的on_init会转发到派生类DerivedEngine::on_init
  3. 此时派生类的成员points_(std::vector<Point*>)还未完成初始化——派生类成员的初始化要等到基类构造完全结束后才会执行
  4. 对未初始化的std::vector调用push_back属于未定义行为,直接触发了段错误(GDB输出中__p=0x0也验证了这一点:vector的底层存储指针为空,allocator无法在无效地址上构造对象)

替换unique_ptr无效的原因也很明确:问题核心不是存储的指针类型,而是vector本身未被正确初始化。

解决方案

方案1:延迟初始化逻辑,构造完成后手动调用on_init

修改基类构造函数,移除内部的on_init调用,让用户在对象构造完成后手动触发初始化:

#include <vector>
#include <unordered_map>
#include <iostream>

struct Data
{
     double x_ = 3.0;
     double y_ = 3.14;
};

template<typename Derived>
class AbstractEngine
{
public:
    AbstractEngine(int i)
    {
        add_data(i);
        auto data = view_data(i);
        std::cout << "Added data: " << data->x_ << " " << data << std::endl;
        // 移除此处的on_init调用
    }

    void on_init()
    {
      static_cast<Derived*>(this)->on_init();
    }

    void add_data(int i)
    {
        data_[i] = new Data(); 
    }

    Data* view_data(int i)
    {
        return data_[i];
    }

private:
    std::unordered_map<int, Data*> data_;
};

struct Point
{
    Point(double x) : x_(x) {} 
    double x_;
};

class DerivedEngine : public AbstractEngine<DerivedEngine>
{
public:
    DerivedEngine(int i) :
        AbstractEngine<DerivedEngine>(i) {}

    void on_init()
    {
        int i = 3;
        auto data = view_data(i);
        std::cout << "Viewed data: " << data->x_ << " " << data << std::endl;
    
        points_.push_back(new Point(3.14));
        std::cout << "Point pushed successfully" << std::endl;
    }
private:
    std::vector<Point*> points_;
};


int main()
{
    DerivedEngine engine(3);
    engine.on_init(); // 对象构造完成后手动调用初始化
}

方案2:使用工厂方法确保初始化顺序

通过静态工厂函数,先完成派生类对象的完整构造,再调用on_init,避免基类构造时访问未初始化的派生类成员:

#include <vector>
#include <unordered_map>
#include <iostream>

struct Data
{
     double x_ = 3.0;
     double y_ = 3.14;
};

template<typename Derived>
class AbstractEngine
{
protected:
    // 将基类构造函数设为protected,强制通过工厂方法创建对象
    AbstractEngine(int i)
    {
        add_data(i);
        auto data = view_data(i);
        std::cout << "Added data: " << data->x_ << " " << data << std::endl;
    }

public:
    template<typename... Args>
    static Derived create(Args&&... args)
    {
        Derived obj(std::forward<Args>(args)...); // 完成派生类全量构造
        obj.on_init(); // 此时派生类成员已初始化
        return obj;
    }

    void on_init()
    {
      static_cast<Derived*>(this)->on_init();
    }

    void add_data(int i)
    {
        data_[i] = new Data(); 
    }

    Data* view_data(int i)
    {
        return data_[i];
    }

private:
    std::unordered_map<int, Data*> data_;
};

struct Point
{
    Point(double x) : x_(x) {} 
    double x_;
};

class DerivedEngine : public AbstractEngine<DerivedEngine>
{
public:
    // 派生类构造函数设为public或protected,配合基类工厂方法
    DerivedEngine(int i) :
        AbstractEngine<DerivedEngine>(i) {}

    void on_init()
    {
        int i = 3;
        auto data = view_data(i);
        std::cout << "Viewed data: " << data->x_ << " " << data << std::endl;
    
        points_.push_back(new Point(3.14));
        std::cout << "Point pushed successfully" << std::endl;
    }
private:
    std::vector<Point*> points_;
};


int main()
{
    auto engine = DerivedEngine::create(3); // 通过工厂方法创建并初始化
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 16:54:50