单例销毁的 atexit :失败案例

atexit for singleton destruction : failure case

发件人:https://sourcemaking.com/design_patterns/to_kill_a_singleton

One thing's for sure: you can't use more than one destroyer if the singleton destructors depend on one another. An alternative is to eschew destroyers altogether and rely instead on the draft-standard atexit() function, as Tim Peierls suggested to me: I maintain that atexit() is a good way to cleanup singletons in C++ when you really want single instances with program lifetime and no replacement.

The draft standard promises a lot: The function atexit() from can be used to specify a function to be called at exit. If atexit() is to be called, the implementation shall not destroy objects initialized before an atexit() call until after the function specified in the atexit() call has been called.

The only way I can see this failing is if a statically initialized object whose destructor depends on a Singleton instance is initialized after the Singleton instance is constructed, i.e., through some other static initialization. This suggests that classes having static instances should avoid depending on singletons during destruction. (Or at least there should be a way for such classes to check for the existence of the Singleton during destruction.)

我无法理解最后一段,即在什么情况下它会失败以及如何失败。

有人可以解释一下吗。

由于使用atexit而不是析构函数来清理单例,因此可以更改对象清理的顺序。例如:

Singleton S;
Object O;
// later in code:
Call atexit() to register cleanup function for S

通常这些对象的销毁顺序是 O 然后是 S,但是随着 atexit 调用的添加,这是相反的,因此 S 在 atexit 调用中被清理,然后 O 是被毁。如果 O 的析构函数以任何方式依赖于 Singleton S,那么当该析构函数为 运行.

时,您将有未定义的行为

避免这种情况的方法是调用 atexit 来注册 Singleton 清理函数,然后再构造任何依赖它的对象。如果 O 本身是一个静态对象,这可能会很棘手,可能需要创建一个 class 其构造函数调用 atexit 以便它可以插入两个静态对象之间。

Singleton S;
struct SAtExit {
     SAtExit() { atexit(...); }
} SCleanup;
Object O;