Does C++ Call Destructors For Global and Class Static Variables

Does C++ call destructors for global and class static variables?

From § 3.6.3 of the C++03 standard:

Destructors (12.4) for initialized objects of static storage duration (declared at block scope or at namespace scope) are called as a result of returning from main and as a result of calling exit (18.3). These objects are destroyed in the reverse order of the completion of their constructor or of the completion of their dynamic initialization. If an object is initialized statically, the object is destroyed in the same order as if the object was dynamically initialized. For an object of array or class type, all subobjects of that object are destroyed before any local object with static storage duration initialized during the construction of the sub- objects is destroyed.

Furthermore, § 9.4.2 7 states:

Static data members are initialized and destroyed exactly like non-local objects (3.6.2, 3.6.3).

However, if a destructor has no observable behavior, it may not be invoked. Terry Mahaffey details this in his answer to "Is a C++ destructor guaranteed not to be called until the end of the block?" .

Why destructor of global static variable is not called?

Why would the destructor get called ? You're not deleting the object. In other words, you have a memory leak.

You could fix this by including this in the end of main():

delete pSingletone;

You would have to make B::~B() public, though.

Destruction of static member in a class with global instance

First,

bool dummy = MyClass::InitStaticMember(); // m_object is initialized here

Doesn't actually intialize the static member. That happens at the line before

SomeObject MyClass::m_object;

So since you essentially have

SomeObject MyClass::m_object;
MyClass g_my_global_class;

and since objects are destroyed in the reverse order then g_my_global_class is destroyed before MyClass::m_object.

Now, if you move MyClass g_my_global_class; to a different translation unit then all bets are off. The ordering is only guaranteed in a single translation unit.

Will (global) static variables be destroyed at program end?

The destructors of file or namespace scope objects get called when the control flow leaves main().

If an exception leaves main() then it's implementation defined whether the destructors of any objects get called. With modern compilers the destructors won't be called in this case to allow easy inspection of the program state when the unhandled exception was thrown. Early C++ implementations used exception mechanism based on setjmp/longjmp which would unwind the stack while searching for the exception handler and hence calling destructors even if no suitable exception handler was eventually found.

If an application terminates with _exit() or _Exit() or std::quick_exit() no destructors get called.

Static global structure's destructor not being called

I was running the above program as part of a Google test that exits main by a call to _exit(). And it seems that destructors for static global objects aren't called when a program is terminated by a call to _exit(). See this answer and this

what is the destruction order between global object and static variable?

Standard section 3.8 says:

The lifetime of an object of type T ends when:

  • if T is a class type with a non-trivial destructor (12.4), the destructor call starts, or

  • the storage which the object occupies is reused or released.

Now int is not a class type, and since Array::counter has static storage duration, its storage is never released. So the lifetime of Array::counter never ends, and you can safely access it from any destructor you want!

Destructor of a global static variable in a shared library is not called on dlclose

There is no guarantee that unloading (destructors are invoked) happens on dlclose. On musl (as opposed to glibc), constructors only run the first time a library is run, and destructors only run on exit. For portable code, dlclose cannot be assumed to unload the symbols immediately.

The unload behavior depends on glibc's symbol binding when doing dynamic linking, and is independent of GCC.

The static variable get::i has a STB_GNU_UNIQUE binding. For static variables in inline functions, the uniqueness of the object is assured by the ELF linker. However, for dynamic loading, the dynamic linker assures uniqueness by marking the symbol STB_GNU_UNIQUE. Hence, another attempt to dlopen the same shared library by some other code will lookup the symbol and find that it is unique and return the existent one from the unique symbols table. A symbol with unique binding cannot be unloaded.

Unique binding can be disabled with -fno-gnu-unique if not needed.

References

Bug that I raised to GCC

STB_GNU_UNIQUE

Destructor called twice with static object

why is this happening?

Because the variable is declared static. This means that the variable has internal linkage. Which means that each translation unit has their own object. You have defined the variable in two translation units, and therefore you have two objects.

If you didn't want this, then the variable shouldn't be static. An easy solution is to declare it inline instead. This allows it to have external linkage while still being defined in the header.

P.S. Be very careful of Static Initialisation Order Fiasco. Try to avoid variables of static storage when you can, especially those in namespace scope.

are C++ static variables always destructed on main thread?

Destructors of the global objects are called by std::exit. That function is called by the C++ run-time when main returns.

It is possible to arrange for std::exit to be called by a thread other than that which entered main. E.g.:

struct A
{
A() { std::cout << std::this_thread::get_id() << '\n'; }
~A() { std::cout << std::this_thread::get_id() << '\n'; }
};

A a;

int main() {
std::thread([]() { std::exit(0); }).join();
}

Outputs:

140599080433472
140599061243648

Showing that one thread called the constructor and another the destructor.

See std::exit and std::atexit for more details.

How are the private destructors of static objects called?

Section 3.6.3.2 of the C++03 standard says:

Destructors for initialized objects of static storage duration (declared at block scope or at namespace scope) are called as a result of returning from main and as a result of calling exit.

It doesn't give any restriction regarding having a private destructor, so basically if it gets created it will also get destroyed.

A private destructor does cause a restriction on the ability to declare an object (C++03 12.4.10)

A program is ill-formed if an object of class type or array thereof is declared and the destructor for the class is not accessible at the point of declaration

but since the destructor of A::theMainInstance is accessible at the point of declaration, your example should have no error.



Related Topics



Leave a reply



Submit