G++ 错误地获取了静态变量的销毁顺序
G++ gets order of destruction of static variables wrong
我有以下类尝试实现通用单例。
struct BaseObject
{
virtual ~BaseObject() {}
};
class _helper
{
private:
template<typename T> friend class Singleton;
set<BaseObject*> _s;
static _helper& _get()
{
static _helper t;
return t;
}
_helper()
{
cout<<" _helper ctor"<<endl;
}
~_helper()
{
cout<<" _helper dtor"<<endl;
//assert(_s.empty());
}
};
// Singleton<foo>::Instance() returns a unique instance of foo
template <typename T>
class Singleton : virtual private T
{
public:
static T& Instance()
{
static Singleton<T> _T;
return _T;
}
private:
Singleton()
{
cout<<"inserting into helper "<<typeid(T).name()<<" ptr "<<this<<endl;
assert(!_helper::_get()._s.count(this));
_helper::_get()._s.insert(this);
}
~Singleton()
{
cout<<"erasing from helper "<<typeid(T).name()<<" ptr "<<this<<endl;
assert(_helper::_get()._s.count(this));
_helper::_get()._s.erase(this);
}
};
现在,如果我调用Singleton< bar>::Instance()
后跟 Singleton< foo>::Instance()
,我应该看到以下输出:
inserting into helper 3bar ptr 0x509630
_helper ctor
inserting into helper 3foo ptr 0x509588
erasing from helper 3foo ptr 0x509588
erasing from helper 3bar ptr 0x509630
_helper dtor
但是在某些情况下,我看到以下内容:
inserting into helper 3bar ptr 0x509630
_helper ctor
inserting into helper 3foo ptr 0x509588
erasing from helper 3bar ptr 0x509630
_helper dtor
erasing from helper 3foo ptr 0x509588
请注意,在第二种情况下,bar
和 foo
的销毁顺序与它们的构造顺序相同。当foo
和bar
单例在共享库 (.so( 中实例化为静态引用时,似乎会发生这种情况:
static bar& b = Singleton<bar>::Instance();
static foo& f = Singleton<foo>::Instance();
知道为什么会这样做吗?
如果单例和帮助程序位于不同的翻译单元或不同的共享对象中,则可能会发生这种情况。请记住,很难预测模板实例最终会采用哪个翻译单元。还要记住,每个共享对象都可以获得自己的实例,例如Singleton<foo>::_T
。所以你有某种每个共享对象的单例(恕我直言,不是很有用(。
请注意,在从中移除最后一个对象之前,您的帮助程序将被销毁。这将导致程序在退出时崩溃。是的,这件事发生在我身上。您需要在 _helper 类中实现一个对象计数器,以便在至少有一个对象注册到它之前不会销毁它。或者,分配堆上的所有单一实例,并让帮助程序在其生存期结束时销毁它们。
update 如果两个静态对象由同一动态库拥有,则可能不会发生此销毁顺序反转。否则,它绝对可以而且确实会发生。这里建议程序员不要跨动态库边界导出静态对象。
据我所知,static _helper t;
定义了一个地址。
static _helper& _get()
{
static _helper t;
return t;
}
但看起来您正在尝试将其用于 2 个不同的对象。
无论如何,我从未见过模板用于单例。在你的情况下,看起来你正试图摧毁一个单例。那也是我不记得以前见过的。单例通常创建一次,并一直存在到您离开程序(并且在您离开程序时仍会分配(。
否则,您可能想要查看共享指针或侵入性引用计数对象?
- 在循环中按顺序遍历成员变量
- C++编译器是否优化了顺序静态变量读取?
- 按字母顺序对结构内数组变量中的名称进行排序
- 字符串变量顺序
- 变量按什么顺序相乘
- 视觉C++:在 DLL 加载期间,全局变量初始化顺序是否具有确定性?
- 线程局部变量的初始化顺序
- 有了memory_order_relaxed,原子变量的总修改顺序如何在典型体系结构上得到保证
- 类静态变量初始化顺序
- 具有静态存储持续时间的常量初始化变量的初始化顺序
- 使用 while 循环显示顺序变量的值
- 同一函数中的静态函数变量初始化顺序
- 当变量的顺序发生变化时C++双倍乘法会产生不同的结果
- C 11指定静态/全局变量的构造顺序
- 单个Cout中单个变量的多个更新的顺序
- 为什么在定义静态成员变量时不遵循定义顺序
- 静态全局变量初始化顺序
- 类模板中成员变量的顺序
- 我可以在C 中更改静态变量初始化顺序吗?
- C++全局变量初始化顺序