user6709725
user6709725

Reputation:

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.

Upvotes: 0

Views: 76

Answers (2)

HolyBlackCat
HolyBlackCat

Reputation: 96043

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.

Upvotes: 3

Edward
Edward

Reputation: 567

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.

Upvotes: -1

Related Questions