1

I have the following piece of code. I have abstracted out and my class looks something like this:

#include<iostream>
#include<map>

using namespace std;

template <class K>
class Base {
    private:
        static std::map<std::string, Base*> derived_map;
        //other private data
    public:
        Base(std::string modName) {
            if (derived_map.find(modName) == derived_map.end())
            {
                derived_map.insert(make_pair(modName, this));
            }
        }

};

template <class K> std::map<std::string, Base<K>*> Base<K>::derived_map;

class Derived: public Base<Derived>
{
    public:
    Derived(std::string modname): Base<Derived>(modname)
    {
    }
};


Derived obj("derived1"); // <<< This casuses segfault
int main()
{
}

When I declare the Derived obj globally, it segfaults. When I declared the Derived obj inside of my main then it doesn't. I am not able to figure out what I might be doing wrong. I am trying to maintain a list of derived class pointers in my base class using a std::map. Any clues ?

Pradeep Nayak
  • 675
  • 1
  • 10
  • 24
  • Possible duplicate of http://stackoverflow.com/questions/1819131/c-static-member-initalization-template-fun-inside – Tony Delroy Nov 25 '14 at 06:08
  • [OT]: no need to check is element is already present before to try to insert it in `map`, `map` already does that. – Jarod42 Nov 25 '14 at 08:24

1 Answers1

1

You have 2 global variables with dependencies:

obj requires that Base<Derived>::derived_map is initialized correctly.

global initialization across translation unit is done in undefined order.

You may solve your code with something like:

template <class K>
class Base {
    private:
        static std::map<std::string, Base*>& get_derived_map()
        {
             static std::map<std::string, Base*> derived_map; // initialized the first time
                                                              // get_derived_map is called
             return derived_map;
        }
        //other private data
    public:
        explicit Base(const std::string& modName) {
            get_derived_map().insert(make_pair(modName, this));
        }
};
Jarod42
  • 203,559
  • 14
  • 181
  • 302