c – 共享库中静态函数成员的销毁顺序
我正在探索与单身人士相关的Boost.Serialization中一个非常棘手的错误.对于上下文:Boost 1.65更改了单例的实现,打破了is_destructed通知,导致程序退出或库卸载时出现段错误.提升1.66“固定”这个,但泄漏记忆.
单例代码(与此问题相关)归结为: template<class T> struct singleton{ T& inst(){ static T t; return t; } } 使用静态成员函数变量可以避免使用static init fiasco,但仍然存在与销毁相同的问题. 然而,Finding C++ static initialization order problems显示了代码如何解决:当A的Ctor使用B时,B将首先被构造,因此最后被破坏.这也在Destruction order of static objects in C++中说明.(析构函数的完成以与构造函数完成相反的顺序发生) 到现在为止还挺好. Boost.Serialization现在使用类型为extended_type_info_typeid< T>的多个单体.在另一个单独的std :: multiset< const bs :: typeid_system :: extended_type_info_typeid_0 *,...>中注册usertype T的一些元数据.这是通过使用extended_type_info_typeid_0的构造函数中的multiset(假设来自此处的所有单例)来完成的.在extended_type_info_typeid_0的析构函数中,删除了多集中的条目. 这意味着我们完全具有上述情况,并且multiset应该比其他实例更长. 这在使用共享库时会中断.我有以下测试用例: test_multi_singleton.cpp: int f(); int g(); int main(int argc,char**){ // Make sure symbols are used if(argc==8) return f(); if(argc==9) return g(); } multi_singleton1.cpp: #include <boost/serialization/extended_type_info_typeid.hpp> int f(){ return 0 != boost::serialization::extended_type_info_typeid<int>::get_const_instance().get_key(); } multi_singleton2.cpp: #include <boost/serialization/extended_type_info_typeid.hpp> int g(){ // Use different(!) type return 0 != boost::serialization::extended_type_info_typeid<float>::get_const_instance().get_key(); } Build with: g++ multi_singleton1.cpp -lboost_serialization -fPIC -shared -olibmulti_singleton1.so g++ multi_singleton2.cpp -lboost_serialization -fPIC -shared -olibmulti_singleton2.so g++ test_multi_singleton.cpp -L. -lmulti_singleton1 -lmulti_singleton2 Run in valgrind: valgrind ./a.out 可以看出,这会破坏Boost 1.65中的记忆.原因是我通过劫持和记录ctor / dtor调用来追踪混乱的顺序: ctor 0x7f9f0aa074a0 std::multiset<const extended_type_info_typeid_0*> ctor 0x7f9f0a7f63e0 extended_type_info_typeid<float> ctor 0x7f9f0a7f64a0 std::multiset<const extended_type_info_typeid_0*> ctor 0x7f9f0aa073e0 extended_type_info_typeid<int> dtor 0x7f9f0aa073e0 extended_type_info_typeid<int> dtor 0x7f9f0aa074a0 std::multiset<const extended_type_info_typeid_0*> dtor 0x7f9f0a7f64a0 std::multiset<const extended_type_info_typeid_0*> dtor 0x7f9f0a7f63e0 extended_type_info_typeid<float> 这是使用GCC 6.4,但与GCC 7.1相同.正如您所看到的那样,2个多重集合在第二个extended_type_info_typeid之前被一起销毁. 我错过了什么吗?这是C标准允许的吗? 解决方法
从
basic.start.term/3开始:
也:
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |