I have a function that I want to run whenever my program exits:
void foo() {
std::cout<< "Exiting" << std::endl;
}
How do I register it to be run whenever the program exists, regardless of when and why it exits - due to signal, exit() call, etc?
C library function - exit() The C library function void exit(int status) terminates the calling process immediately. Any open file descriptors belonging to the process are closed and any children of the process are inherited by process 1, init, and the process parent is sent a SIGCHLD signal.
The exit function is specified in the < stdlib. h > header and is included in the C standard libraries. The <stdlib.
Under any version of the language, exit requires a single argument of type int . Passing 0 or EXIT_SUCCESS (a macro defined in <stdlib. h> causes the program to terminate and pass a status to the environment indicating success. Passing EXIT_FAILURE causes the program to terminate with a status indicating failure.
A return statement ends the execution of a function, and returns control to the calling function. Execution resumes in the calling function at the point immediately following the call.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With