注册对对象工厂的调用会导致段错误



我正在尝试用 c++ 构建一个简单的对象工厂。到目前为止,我有以下代码:

工厂:

class Factory{
public:
TCreateMethod = std::function<Simulation*(std::string)>;
public:
Factory() = delete;
static bool Register(const std::string name, TCreateMethod funcCreate){
const auto [it, success] = s_methods.insert({name, funcCreate});
return success;
};
static Simulation* Create(const std::string name, const std::string ini_file){
if (auto it = s_methods.find(name); it != s_methods.end()){
return it->second(ini_file);
}
return nullptr;
};
private:
static std::map<std::string, TCreateMethod> s_methods;
};
std::map<std::string, Factory::TCreateMethod> Factory::s_methods;

对象:

class SimulationStuff : public Simulation{
public:
SimulationStuff(std::string ini_file);
static Simulation* createMethod(std::string ini_file){
return new SimulationStuff(ini_file);
};
static std::string getFactoryName(){
return "SimulationStuff";
};
private
static bool s_registerd;
};
bool SimulationStuff::s_registered = Factory::Register(SimulationStuff::getFactoryName(), SimulationStuff::createMethod);

赛格夫的回溯:

#0  0x00007ffff75ae44a in ?? () from /lib/x86_64-linux-gnu/libstdc++.so.6
#1  0x00005555556192a1 in std::_Rb_tree_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::function<Simulation* (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)> > >::operator--() (this=0x7fffffffd820)
at /usr/include/c++/8/bits/stl_tree.h:302
#2  0x0000555555618e36 in std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::function<Simulation* (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)> >, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::function<Simulation* (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)> > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::function<Simulation* (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)> > > >::_M_get_insert_unique_pos(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (this=0x5555557bc180 <Factory::s_methods[abi:cxx11]>, __k="SimulationStuff")
at /usr/include/c++/8/bits/stl_tree.h:2063
#3  0x0000555555618b05 in std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::function<Simulation* (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)> >, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::function<Simulation* (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)> > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::function<Simulation* (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)> > > >::_M_insert_unique<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::function<Simulation* (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)> > >(std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::function<Simulation* (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)> >&&) (this=0x5555557bc180 <Factory::s_methods[abi:cxx11]>, __v=...)
at /usr/include/c++/8/bits/stl_tree.h:2106
#4  0x00005555556188b2 in std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::function<Simulation* (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)>, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::function<Simulation* (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)> > > >::insert(std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::function<Simulation* (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)> >&&) (
this=0x5555557bc180 Factory::s_methods[abi:cxx11]>, __x=...) at /usr/include/c++/8/bits/stl_map.h:809
#5  0x00005555556184ab in Factory::Register(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::function<Simulation* (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)>) (name="SimulationStuff", funcCreate=...)
at src/factory.cpp:13
#6  0x000055555560ca19 in __static_initialization_and_destruction_0 (__initialize_p=1, __priority=65535) at src/simulation_stuff.cpp:24
#7  0x000055555560ca7e in _GLOBAL__sub_I__ZN28SimulationStuff12s_registeredE () at src/simulation_stuff.cpp:73
#8  0x00005555556c3d75 in __libc_csu_init ()
#9  0x00007ffff71aa02a in __libc_start_main (main=0x55555569f7eb <main(int, char**)>, argc=1, argv=0x7fffffffdb88, init=0x5555556c3d30 <__libc_csu_init>, 
fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffdb78) at ../csu/libc-start.c:264
#10 0x00005555555a5a6a in _start ()

我遇到的问题是我无法理解为什么会发生 segv,因为s_methods映射应该在编译时初始化为 0,s_registered应该在程序开始时初始化。

你已经违反了静态初始化顺序的惨败。 未指定在不同编译单元中定义的具有静态生存期的对象(如全局和静态类成员(的初始化顺序。 完全有可能在Factory::s_methods之前初始化SimulationStuff::s_registered。 如果发生这种情况,则当您尝试插入std::map

,不会初始化它。若要解决此问题,请在首次使用时构造注册表映射。 即:

class Factory {
// ...
static std::map<std::string, TCreateMethod>& getMethods() {
static std::map<std::string, TCreateMehtod> methods;
return methods;
}
static bool Register(const std::string name, TCreateMethod funcCreate){
const auto [it, success] = getMethods().insert({name, funcCreate});
return success;
};
// ...
};

最新更新