Question: is there a way to tell GCC to call a function before main() but after all constructors (including __attribute__ ((constructor)) and globally scoped static variables)?
Background: I have a shared library which needs to automatically provide some capability on loading and clean up after itself on exit. The "on loading" functionality is handled by defining a set of functions with __attribute__ ((constructor)). These constructor functions may interact with globally scoped static variables. Some of these constructor functions may further register atexit() handler to take care of the cleanup requirement. The catch is that my exit handler needs to access those static variables. Unfortunately, some of those static variables are declared an inner scopes (e.g. inside functions), which means that their destructors get called before the exit handler. This results in "use after free" type functionality.
The easiest way to demonstrate this problem is with the following code
#include <iostream>
class A
{
public:
A() { std::cout << "A ctor" << std::endl; }
~A() { std::cout << "A dtor" << std::endl; }
void doit() { std::cout << "Exit handler cleanup" << std::endl; }
};
static A a;
static void my_handler()
{
a.doit();
}
__attribute__ ((constructor)) void prepare_exit_handler(void)
{
printf("Foo constructor function\n");
atexit(my_handler);
}
int main()
{
std::cout << "Start of main" << std::endl;
exit(1);
}
When executed, this outputs
Foo constructor function
A ctor
Start of main
A dtor
Exit handler cleanup
The last line of the output shows that a.doit() is executed after a is destructed.
One possibility I considered was to use init_priroty attribute to force the atexit() call to happen after all static variables are instantiated, thus guaranteeing the exit handler will get executed before static variable destructors.
__attribute__ ((constructor)) __attribute__ ((init_priority (65535))) void prepare_exit_handler(void)
However, this causes a compile time error
error: can only use ‘init_priority’ attribute on file-scope definitions of objects of class type
UPDATE 1 - apparently the correct way to specify init priority for constructors is with __attribute__ ((constructor(65535))). However, even the last priority (highest legal number, 65535) appears to be before static constructors are called.
UPDATE 2 - I think I found the magic combination of attributes which works as desired. There is one downfall - it requires explicitly specifying init_priority on all of my static variables. Is there a way around that limitation?
#include <iostream>
class A
{
public:
A() { printf("A ctor\n"); }
~A() { printf("A dtor\n"); }
void doit() { std::cout << "Exit handler cleanup" << std::endl; }
};
static __attribute__ ((init_priority(1001))) A a;
static void my_handler()
{
a.doit();
}
__attribute__ ((constructor(65535))) void prepare_exit_handler(void)
{
printf("Registering atexit\n");
atexit(my_handler);
}
int main()
{
std::cout << "Start of main" << std::endl;
exit(1);
}
which produces
A ctor
Registering atexit
Start of main
Exit handler cleanup
A dtor