具有 std::map 个指向模板对象的指针的 SIGSEGV

SIGSEGV with std::map of pointers to template objects

我需要保留 std::map 个指向模板化对象的指针。 为了摆脱模板,我使用了一个通用的非模板化基础 class.

当 运行 代码时,我得到一个 SIGSEGV 信号。 调试发现问题出在statement

data_[id] = s;

这可能是与对象初始化顺序有关的问题。

代码如下所示:

文件shared_iface.h:

class shared_iface {
    unsigned long int counter_;
};

文件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_;
};

文件communication_handler.h:

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

文件communication_handler.cpp:

CommunicationHandler comm;

文件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_;
};

文件main.cpp:

#include "shared.hpp"

shared<int> c;

int main ()
{
    return 1;
}

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

猜对了。 c 是类型 shared<int> 的静态对象。 shared<T>的构造函数依赖于静态对象commc 很可能在 comm 之前被初始化,你会得到未定义的行为。 comm 本来可以先初始化的,幸好你的代码没用。

这称为 static initialization order fiasco. The usual way to avoid the fiasco is Construct On First Use Idiom,但一般来说,避免依赖于其他静态对象的静态对象。