I have a main program (main.cpp
) and a shared library (test.h
and test.cpp
):
test.h:
#include <stdio.h>
struct A {
A() { printf("A ctor\n"); }
~A() { printf("A dtor\n"); }
};
A& getA();
test.cpp:
#include "test.h"
A& getA() {
static A a;
return a;
}
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;
}
This is how I compile these sources on Linux:
g++ -shared -fPIC test.cpp -o libtest.so
g++ main.cpp -ltest
Output on Linux:
B ctor
A ctor
A dtor
B dtor
When I run this example on Windows (after some adjustments like adding dllexport
) I get with MSVS 2015/2017:
B ctor
A ctor
B dtor
A dtor
To me the first output seems to be compliant with the standard. For example see: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf
From paragraph 3.6.3.1:
If the completion of the constructor or dynamic initialization of an object with static storage duration is sequenced before that of another, the completion of the destructor of the second is sequenced before the initiation of the destructor of the first.
That is if B
object is constructed first it should be destroyed last - that what we see on Linux. But the Windows output is different. Is it a MSVC bug or am I missing something?
The whole concept of a DLL is outside the scope of the C++ standard.
With Windows, DLLs can be unloaded dynamically during program execution. To help support this, each DLL will handle the destruction of static variables constructed while it was loaded. The result is that the static variables will be destroyed in an order that depends on the unload order of the DLLs (when they receive the DLL_PROCESS_DETACH notification). DLLs and Visual C++ run-time library behavior describes this process.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With