简体   繁体   中英

segment fault when inserting element into a gloable std::map in c++

This problem blocks me moving ahead. Please anyone kindly help me out.

My purpose is to implement a plugin factory which can create a plugin object by it's name(something like reflection, I guess?),

I define a namespace in header like:

// header file
namespace PluginFactory
{
  using MFP = std::function<IPlugin*()>;
  typedef std::map<std::string, MFP > mapType;

  extern mapType  g_ConstructMap;
  //extern std::map<std::string, int> mMap;

  extern IPlugin *CreateInstance(const std::string &className);

  template<typename T>
  IPlugin * createPlugin()
  {
    return new T;
  }

  template <typename T>
  extern void InsertMap(const std::string &pluginName)
  {
    g_ConstructMap.insert(std::make_pair(pluginName, &createPlugin<T>));
    //mMap.insert(std::make_pair(pluginName, 0));
  }
}
// source file
namespace  PluginFactory
{

  mapType  g_ConstructMap;
  std::map<std::string, int> mMap;

  IPlugin * CreateInstance(const std::string &className)
  {
    mapType::iterator it = g_ConstructMap.find(className);
    if(it == g_ConstructMap.end())
    {
      qWarning("Construct %s failed. Not find a construct in map.", className.c_str());
      return nullptr;
    }
    return it->second();
  }
}

and the register

template<typename T>
class PluginFactoryRegister
{
public:
  PluginFactoryRegister(const std::string &pluginName)
  {
    PluginFactory::InsertMap<T>(pluginName);
  }
};

Register a specific plugin class into this system, using the macro:

#define REGISTER_DEF_TYPE(NAME) \
    PluginFactoryRegister<NAME> NAME::regTbl(#NAME)

#define ADD_REGISTER_TABLE(NAME) \
    static PluginFactoryRegister<NAME> regTbl

Finnaly, call insert function in PluginFactoryRegister .

But, every time I run application, it complains Segment fault in exactly line:

namespace PluginFactory
{
...
   g_ConstructMap.insert(std::make_pair(pluginName, &createPlugin<T>));
...
}

[Update 1] I'm using two macros for adding specific plugin classes(more than two such subclass) into my 'reflection system', like:

// example_plugin.h
class ExamplePlugin: public IPlugin
{
 //...

 // reflection
 ADD_REGISTER_TABLE(ExamplePlugin);
}
// example_plugin.cpp

 // ...
 REGISTER_DEF_TYPE(ExamplePlugin);
 // ...

And in some place, I will call CreateInstance for create objects in a loop, like:

for(auto name : classnames)
{
  IPlugin * newPlugin = PluginFactory::CreateInstance(name);
  //...
}

Surely, I have tried many solutions, like define as class static map. That can barely help me.

This looks like a classical static initialization order fiasco .

The solution is to register classes without touching global variables, possibly by putting them into functions and making them static .

Instead of mapType g_ConstructMap , do something like

mapType &g_ConstructMap()
{
    static mapType ret;
    return ret;
}

and so on.

I see a lot of pointers. Are you sure that you've properly initialised the map when you call insert on it?

I'd also suggest smart pointers.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM