SIGSEGV with std::map of pointers to template objects

86 views Asked by At

I need to keep a std::map of pointers to templated objects. To get rid of templates, I use a common untemplated base class.

When running the code, I get a SIGSEGV signal. Debugging shows that the problem arises with statement

data_[id] = s;

It could be a problem related to the order of initialization of the objects.

The code looks like this:

File shared_iface.h:

class shared_iface {
    unsigned long int counter_;
};

File shared.h:

extern CommunicationHandler comm;

template <typename T>
class shared: private shared_iface {
public:
    shared(): data_(nullptr), id_(0) {
        comm.add(id_, this);
    }
private:
    T* data_;
    unsigned long int id_;
};

File communication_handler.h:

class CommunicationHandler {
public:
    inline void add(unsigned long int id, shared_iface* s) {
        data_.add(id, s);
    }
private:
    Dictionary data_;
};

File communication_handler.cpp:

CommunicationHandler comm;

File dictionary.h:

class Dictionary {
public:
    Dictionary() {
        data_.clear();
    }
    void add(unsigned long int id, shared_iface* s) {
        data_[id] = s;
    }
private:
    std::map<unsigned long int, shared_iface*> data_;
};

File main.cpp:

#include "shared.hpp"

shared<int> c;

int main ()
{
    return 1;
}
1

There are 1 answers

1
eerorika On BEST ANSWER

It could be a problem related to the order of initialization of the objects.

A good guess. c is a static object of type shared<int>. The constructor ofshared<T> depends on the static object comm. c may very well be initialized before comm and you'll get undefined behaviour. comm could have been initialized first, you're lucky that your code didn't work.

This is known as static initialization order fiasco. The usual way to avoid the fiasco is Construct On First Use Idiom but in general, avoid static objects that depend on other static objects.