在C++中销毁全局对象和atexit之间的顺序

zel*_*lon 16 c++ atexit order-of-execution global-object

我想知道可以确定在销毁全局对象和atexitC++ 之间的顺序

我有一个全局对象和注册atexit函数如下:

static MyClass g_class;

void onExit()
{
    // do some destruction
}

int main()
{
    atexit(onExit);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我发现onExit()之前MyClass::~MyClass()在Visual Studio 2012和gcc4.7.2中调用过.我确定onExit在全局对象(如g_class)销毁之前总是会调用它吗?

我想知道全局对象寄存器顺序和atexit寄存器顺序使用相同的顺序表.或者全局对象顺序和atexit顺序之间没有关系?

编辑:对不起,我写错了.整理示例代码时我很困惑.onExit()在~MyClass()之前调用.

And*_*owl 16

更新: OP造成了一些混乱,似乎VC11确实表现得像C++ 11标准所规定的那样.以下答案是在假设没有的情况下编写的.

因此,这个问题的答案:

我确定onExit在全局对象(如g_class)销毁之前总是会调用它吗?

只要您使用完全兼容的编译器,就是"是".


我发现MyClass::~MyClass()之前onExit()在Visual Studio 2012中调用过.

如果是这种情况,那么它就是VC11中的一个错误.根据C++ 11标准的第3.6.3/1段:

具有静态存储持续时间的初始化对象(即,其生命周期(3.8)已开始的对象)的析构函数(12.4)被调用作为从main调用返回的结果std::exit(18.5).[...]

另外,根据第3.6.3/3段:

如果在调用std::atexit(参见<cstdlib>,18.5)之前对具有静态存储持续时间的对象的初始化的完成进行了排序,则在调用该对象的析构函数之前对传递给该函数的函数进行std::atexit排序.

因此,在你的情况下,onexit()应该在析构函数之前调用MyClass.

据我所知,Clang 3.2和GCC 4.8.0在这方面是合规的,如本实例所示.

  • @zelon:好的.然后行为是正确的,这是C++标准指定的. (2认同)