当多个(Posix)线程并行调用exit()
时,如何安全地删除静态C ++对象?
在我的CentOS6环境中exit()
执行atexit
(或on_exit
)清理处理程序,通过调用fct[--cnt]()
之类的内容cnt
处理程序注册。当多个线程同时调用exit()
时,我们在未受保护的--cnt
操作中遇到竞争条件,并且可能会多次跳过或调用一些处理程序(导致偶尔崩溃)。
那么我怎样才能确保只有一个exit()
调用线程进行清理而其他所有线程都停止了?请注意,将pthread_mutex_lock()
插入清理处理程序没有帮助,因为可能会跳过此处理程序...
不幸的是我无法避免多个线程调用exit()
,因为我的用户将编写代码(我正在为他们提供一个库)。
寻找安全的想法,谢谢!
答案 0 :(得分:1)
没有可移植的方法来处理对exit()的多次调用 - 因为它是未定义的(行为)在这种情况下会发生什么。
但是,对于某些特定平台,您可能会找到一种方法。对于"多次调用的一种通用解决方案"是在你的静态对象中有一个标志,比如"我已经被破坏了#34;。像往常一样,您可以在模板中隐藏它:
template <typename T> class StaticExitHandled {
public:
std::unique_ptr<T> t_;
~StaticExitHandled() { t_.release(); }
};
现在只记得使用此模板声明所有静态对象。这只是它的核心,根据您的口味添加铃声和口哨声。而且,而不是std :: unique_ptr&lt;&gt;你可以使用boost :: optional&lt;&gt;或者其他一些东西。
我不认为有一个通用的解决方案,而且根本没有打电话#34;
实际上,我建议不要在多线程环境中使用非平凡的静态对象。因此,只有静态POD和具有严格约束的析构函数的对象(取决于在您的环境中此时安全做什么 - 即在大多数环境中关闭文件句柄是正常的。)
答案 1 :(得分:0)
如果你正在使用gcc,你可以使用下面的代码来定义清理程序:
void __attribute__ ((destructor)) my_fini(void);
如果这没有解决您的问题,如何定义具有静态持续时间的单个对象,其析构函数将负责您的清理?