I have a function that I want to run whenever my program exits:
void foo() {
std::cout<< \"Exiting\" << std::endl;
}
How do I reg
You can use the aptly named std::atexit function in the cstdlib
header:
#include <cstdlib>
void exiting() {
std::cout << "Exiting";
}
int main() {
std::atexit(exiting);
}
The system will maintain a stack of functions registered with atexit
and call them each in the reverse order of their registration when either the exit
function is called, or the program returns from main
. You can register at least 32 functions this way.
The only way (in Unix and Unix-like operating systems) to regain control after a process exits is to wait(2)
for it. Short of a powerfail, kernel panic, or forced reboot, this should work:
#include <sys/types.h>
#include <sys/wait.h>
#include <iostream>
int AtExit() {
pid_t pid = fork();
if(pid < 0) return pid;
if(pid == 0) return pid;
pid = waitpid(pid, 0, 0);
return pid;
}
int main () {
if(AtExit()) {
std::cout << "Exiting\n";
return 0;
}
std::cout << 7 << "\n";
}
I am answering as a Linux user, but all of this should apply to windows.
I had this similar question, so hopefully I can sum up previous answers and add my two cents.
Signals and abort()
: ^C
and ^Z
can be "intercepted" to call your function before exiting, presumably with exit(). Signals SIGQUIT
AKA ^\
and SIGKILL
which has no key stroke cannot be intercepted. Here's an example for using the csignal
header and a C++ lambda.
#include <iostream>
#include <csignal>
#include <cstdlib>
using namespace std;
int main()
{
//signal requires lam take an int parameter
//this parameter is equal to the signals value
auto lam =
[] (int i) { cout << "aborting" << endl; exit(0); };
//^C
signal(SIGINT, lam);
//abort()
signal(SIGABRT, lam);
//sent by "kill" command
signal(SIGTERM, lam);
//^Z
signal(SIGTSTP, lam);
while(1)
{
}
return 0;
}
Exit: Since I used exit()
in my examples above, care must be taken here. If the function being run is a clean-up function that only needs to run once, perhaps a static variable has_run
could be used. Or in the example above, raise()
a signal that you can't intercept. But those tend to come with core dumps which just feels dirty. Your choice, here. An example follows
#include <cstdlib>
#include <iostream>
using namespace std;
int main()
{
//called with no parameters
auto lam = [] () { cout << "at exit"; };
atexit(lam);
return 0;
}
Take note that c++11 added a quick_exit
which has an accompanying at_quick_exit
which act the same as above. But with quick_exit
no clean up tasks are performed. In contrast, with exit
object destructors are called and C streams are closed, with only automatic storage variables not getting cleaned up.
You could put it in the destructor of a class with a global instance.
class SomeGlobalStuff {
~SomeGlobalStuff() {
foo();
}
static SomeGlobalStuff instance;
};
// putting this in a single compilation unit.
SomeGlobalStuff SomeGlobalStuff::instance instance;
But like any other method, you have to remember that you cannot use any data if you cannot garantee that it still exists. Deallocation of global objects is done in a arbitrary order, so basically, you cannot use std::cout in the foo() function. atexit() is worse in this regard, because whether it executes before or after destruction of global objects depends on the compiler and compiler options.
And anyway, you still have to handle signals correctly. You have to choose which signals to handle and which to not handle (you most likely don't want to handle SIGSEGV). You cannot escape signal handling. And remember that signals may interrupt your program at any time (unless masked) so your data structures might be in a arbitrary state, in the middle of an update.