共享库中静态对象的销毁顺序

eXX*_*XX2 13 c++ windows singleton shared-libraries object-destruction

我有一个主程序(main.cpp)和一个共享库(test.htest.cpp):

test.h:

#include <stdio.h>

struct A {
    A() { printf("A ctor\n"); }
    ~A() { printf("A dtor\n"); }
};

A& getA();
Run Code Online (Sandbox Code Playgroud)

TEST.CPP:

#include "test.h"

A& getA() {
    static A a;
    return a;
}
Run Code Online (Sandbox Code Playgroud)

main.cpp中:

#include "test.h"

struct B {
    B() { printf("B ctor\n"); }
    ~B() { printf("B dtor\n"); }
};

B& getB() {
    static B b;
    return b;
}

int main() {
    B& b = getB();
    A& a = getA();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这是我在Linux上编译这些源代码的方法:

g++ -shared -fPIC test.cpp -o libtest.so
g++ main.cpp -ltest
Run Code Online (Sandbox Code Playgroud)

Linux上的输出:

B ctor
A ctor
A dtor
B dtor
Run Code Online (Sandbox Code Playgroud)

当我在Windows上运行此示例(经过一些调整,如添加dllexport)后,我得到MSVS 2015/2017:

B ctor
A ctor
B dtor
A dtor
Run Code Online (Sandbox Code Playgroud)

对我来说,第一个输出似乎符合标准.例如,请参阅:http: //www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf

从第3.6.3.1段开始:

如果具有静态存储持续时间的对象的构造函数或动态初始化的完成先于另一个对象的顺序排序,则在第一个的析构函数的启动之前对第二个的析构函数的完成进行排序.

也就是说,如果B首先构造了对象,那么它应该被最后销毁 - 这就是我们在Linux上看到的.但Windows输出是不同的.这是一个MSVC错误还是我错过了什么?

120*_*arm 9

DLL的整个概念超出了C++标准的范围.

使用Windows,可以在程序执行期间动态卸载DLL.为了帮助支持这一点,每个DLL将处理在加载时构造的静态变量的破坏.结果是静态变量将按照依赖于DLL的卸载顺序的顺序销毁(当它们收到DLL_PROCESS_DETACH通知时). DLL和Visual C++运行时库行为描述了此过程.