Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you run a function on exit in C++

Tags:

c++

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?

like image 887
Nathaniel Flath Avatar asked Feb 22 '12 20:02

Nathaniel Flath


People also ask

How does exit function work in C?

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.

Where is exit function in C?

The exit function is specified in the < stdlib. h > header and is included in the C standard libraries. The <stdlib.

Why exit function is not working in C?

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.

Does return exit a function in C?

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.


2 Answers

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.

like image 151
Seth Carnegie Avatar answered Oct 16 '22 17:10

Seth Carnegie


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.

like image 30
Trés DuBiel Avatar answered Oct 16 '22 19:10

Trés DuBiel