Demystifying C++ - Initialization of Global Variables

From emmtrix Wiki
Jump to navigation Jump to search

In C, the initialization of global variables is restricted to constant expressions. This means that all global variables must be initialized at compile time, and runtime calculations or functions cannot be used. In contrast, C++ allows for more flexible initialization. When global objects or variables in C++ are created that require non-constant initialization or have a constructor, the compiler generates a special initialization function (often referred to as "global constructor"). This function is automatically called at the start of the program, even before the main() function is invoked. The clang or gcc compiler allows the specification of global constructors using the function attribute __attribute__((constructor)).

Furthermore, the C++ compiler generates a special destructor function in the case of global objects with a destructor. This function is registered during the initialization of the global object using the "Itanium ABI" function __cxa_atexit and is automatically called when the program ends normally (e.g., when return is called in the main() function or when exit() is invoked). Additionally, a DSO handle is passed to the function. DSO stands for Dynamic Shared Object, and it allows, for example, separate execution of all destructor functions for shared object (.so) files.

Examples for Global Variable Initialization

The following table shows C++ code and simplified equivalent C.

C++ Code Equivalent C Code
Initialization of Global Variable
double sqrt2 = sqrt(2.0);
__attribute__((constructor)) static void __cxx_global_var_init_sqrt2(void) {
  sqrt2 = sqrt(2.0);
}
Global Variable with Constructor/Destructor
C1 obj;
extern char __dso_handle;

__attribute__((constructor)) static void __cxx_global_var_init_obj(void) {
  C1_ctor_complete(&obj);
  __cxa_atexit(&C1_dtor_complete, &obj, &__dso_handle);
}