Almost verbatim from the standard:
/// 1. Objects with static storage duration are destroyed
/// and functions registered by calling atexit are
/// called. Objects with static storage duration are
/// destroyed in the reverse order of the completion
/// of their constructor.
/// 2. Functions registered with atexit are called in the
/// reverse order of their registration. A function
/// registered with atexit before an object obj1 of static
/// storage duration is initialized will not be called until
/// obj1s destruction has completed. A function registered
/// with atexit after an object obj2 of static storage
/// duration is initialized will be called before obj2
/// destruction starts.
#include <iostream>
static void pre_exit(void) {
std::cout << "@pre_exit" << std::endl;
}
static void post_exit(void) {
std::cout << "@post_exit" << std::endl;
}
struct FIRST {
FIRST() {
atexit(pre_exit);
std::cout << "FIRST::FIRST()" << std::endl;
}
~FIRST() {
std::cout << "FIRST::~FIRST()" << std::endl;
}
};
struct SECOND {
SECOND() { std::cout << "SECOND::SECOND()" << std::endl; }
~SECOND() { std::cout << "SECOND::~SECOND()" << std::endl; }
};
static FIRST _first;
static SECOND _second;
///////////////
int main() {
if (atexit(post_exit)) { /* registration failed */ }
std::cout << "whatever" << std::endl;
std::cout.flush();
return 0;
}
///// the output is:
FIRST::FIRST()
SECOND::SECOND()
whatever
@post_exit
@pre_exit
SECOND::~SECOND()
FIRST::~FIRST()
/// where I would expect it to be:
FIRST::FIRST()
SECOND::SECOND()
whatever
@post_exit
SECOND::~SECOND()
@pre_exit
FIRST::~FIRST()
/// or maybe even
FIRST::FIRST()
SECOND::SECOND()
whatever
@post_exit
SECOND::~SECOND()
FIRST::~FIRST() // pre_exit was registered before FIRST() completed.
@pre_exit
--
Summary: invocation order of functions registered with atexit()
not as expected
Product: gcc
Version: 3.3.3
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: ivan at sierra-da dot com
GCC build triplet: linux/i686/rh9
GCC host triplet: linux/i686/rh9
GCC target triplet: linux/i686/rh9
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=26723