从全局对象的构造函数调用时的atexit排序

时间:2022-09-25 19:05:34

cppreference says about std::atexit :

cppreference说std::atexit:

The functions may be called concurrently with the destruction of the objects with static storage duration and with each other, maintaining the guarantee that if registration of A was sequenced-before the registration of B, then the call to B is sequenced-before the call to A, same applies to the sequencing between static object constructors and calls to atexit

并发功能可能会被毁灭的对象与静态存储时间和对方,维护保证如果测序B的登记注册,然后调用B是调用一个测序,同样适用于静态对象构造函数和调用atexit之间的排序

I understand that passage to mean that, if std::atexit is called during static initialization, the registered function will be called during the destruction of static objects just before the destruction of the static object which was last initialized when the std::atexit that registered the function was called. I also interpret "may be called concurrently" to mean the calls can occur between static object destructions as opposed to the multi-threaded interpretation of the word.

我理解这段话的意思是,如果std::atexit在静态初始化过程中被调用,那么注册函数将在静态对象被破坏之前被调用,而这个静态对象是在调用注册函数的std:::atexit时最后初始化的。我还解释了“可以同时调用”,意思是在静态对象析构之间发生调用,而不是对单词的多线程解释。

What I'm wondering is whether a object is considered as initialized (in the context of this ordering) when it's initialization begins or when it completes. I wrote a short test to test this :

我想知道的是一个对象在初始化开始或完成时是否被视为初始化(在这个排序的上下文中)。我写了一个简短的测试:

#include <cstdlib>
#include <iostream>

struct foo
{
    foo() 
    {
        std::cout << "ctor\n";
        std::atexit([]() { std::cout << "atexit\n"; });
    }
    ~foo()
    {
        std::cout << "dtor\n";
    }
};

foo my_foo;

int main()
{
    return 0;
}

The output I get is (http://cpp.sh/3bllu) :

我得到的输出是(http://cpp.sh/3bllu):

ctor
dtor
atexit

This leads me to believe that my_foo is not considered to be initialized in this context until it's construction finishes. In other words, the function is considered to have been registered before my_foo was initialized so the registered function executes after my_foo's destruction.

这使我相信my_foo在构造完成之前不会被认为是在这个上下文中初始化的。换句话说,这个函数被认为是在my_foo初始化之前注册的,所以注册函数在my_foo销毁后执行。

I can't seem to find anything that would guarantee this behavior and I'm not even entirely sure my initial interpretation of the cited passage is correct. Is the behavior I've described something that I can rely on or is it implementation defined or even undefined behavior?

我似乎找不到任何能保证这种行为的东西,我甚至不能完全确定我对所引用的文章的最初解释是正确的。我所描述的行为是我可以依赖的,还是实现定义的,甚至是未定义的行为?

1 个解决方案

#1


7  

The call to the destructor will happen before the call to the function passed to atexit. From [basic.start.term], p5:

对析构函数的调用将在调用函数传递到atexit之前发生。从[basic.start。p5词):

If a call to std::atexit strongly happens before the completion of the initialization of an object with static storage duration, the call to the destructor for the object is sequenced before the call to the function passed to std::atexit.

如果在具有静态存储持续时间的对象的初始化完成之前,强烈地发生对std:::atexit函数的调用,那么在对传递给std:::atexit函数的调用之前,对对象的析构函数的调用被排序。

#1


7  

The call to the destructor will happen before the call to the function passed to atexit. From [basic.start.term], p5:

对析构函数的调用将在调用函数传递到atexit之前发生。从[basic.start。p5词):

If a call to std::atexit strongly happens before the completion of the initialization of an object with static storage duration, the call to the destructor for the object is sequenced before the call to the function passed to std::atexit.

如果在具有静态存储持续时间的对象的初始化完成之前,强烈地发生对std:::atexit函数的调用,那么在对传递给std:::atexit函数的调用之前,对对象的析构函数的调用被排序。