Below I have provided a minimal working example of the error I am receiving. At a high level, the application segmentation faults at the line where I attempt to push_back
a Point
object into the vector
defined in DerivedEngine
. I have included the derived/CRTP class structure, in case it is material.
GDB provides the following output:
Program received signal SIGSEGV, Segmentation fault.
0x000055555555691d in __gnu_cxx::new_allocator<Point*>::construct<Point*, Point*> (this=0x7fffffffdde8, __p=0x0)
at /usr/include/c++/9/ext/new_allocator.h:146
146 { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
(gdb) list
141 #if __cplusplus >= 201103L
142 template<typename _Up, typename... _Args>
143 void
144 construct(_Up* __p, _Args&&... __args)
145 noexcept(std::is_nothrow_constructible<_Up, _Args...>::value)
146 { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
147
148 template<typename _Up>
149 void
150 destroy(_Up* __p)
The working code example is below:
#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));
}
private:
std::vector<Point*> points_;
};
int main()
{
DerivedEngine engine(3);
}
I have attempted a reformulation using unique_ptr
instead of a raw pointer, but to no avail. I suspect the issue is related to the vector
itself, not the object being pushed into it.
Your constructor of the base-class is calling the method on_init
AbstractEngine(int i)
{
add_data(i);
auto data = view_data(i);
std::cout << "Added data: " << data->x_ << " " << data << std::endl;
on_init();
}
and in that method you care casting to the derived-class
void on_init()
{
static_cast<Derived*>(this)->on_init();
}
you are still in the constructor of the base so the lifetime of the derived class has not started yet.
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));
}
And here you are trying to call push_back
on a member that does not yet exist.