调用std::vector的push_back时触发Segmentation Fault求助排查
段错误原因分析与解决方案:CRTP基类构造中调用派生类方法访问未初始化成员
问题根源
C++对象的构造顺序是先基类、后派生类成员、最后派生类构造函数。你的代码中存在致命逻辑错误:
- 创建
DerivedEngine对象时,首先执行基类AbstractEngine的构造函数 - 基类构造函数里直接调用了
on_init,而CRTP的on_init会转发到派生类DerivedEngine::on_init - 此时派生类的成员
points_(std::vector<Point*>)还未完成初始化——派生类成员的初始化要等到基类构造完全结束后才会执行 - 对未初始化的
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
相关产品推荐
相关产品推荐

