带有std::指向模板对象的指针映射的SIGSEGV

SIGSEGV with std::map of pointers to template objects

本文关键字:SIGSEGV 指针 映射 对象 std 带有      更新时间:2023-10-16

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

当运行代码时,我得到一个SIGSEGV信号。调试显示,问题出现在语句

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;
}

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

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

这就是所谓的静态初始化顺序惨败。通常避免失败的方法是首次使用时构建习惯用法,但一般来说,避免依赖于其他静态对象的静态对象。