views:

3994

answers:

5

In C and C++, what is the difference between exit() and abort()? I am trying to end my program after an error (not an exception).

+7  A: 

abort sends a SIGABRT signal, exit just closes the application performing normal cleanup.

You can handle an abort signal however you want, but the default behavior is to close the application as well with an error code.

abort will not perform object destruction of your static and global members, but exit will.

Of course though when the application is completely closed the operating system will free up any unfreed memory and other resources.

In both abort and exit program termination (assuming you didn't override the default behavior), the return code will be returned to the parent process that started your application.

See the following example:

SomeClassType someobject;

void myProgramIsTerminating1(void)
{
  cout<<"exit function 1"<<endl;
}

void myProgramIsTerminating2(void)
{
  cout<<"exit function 2"<<endl;
}

int main(int argc, char**argv)
{
  atexit (myProgramIsTerminating1);
  atexit (myProgramIsTerminating2);
  //abort();
  return 0;
}

Comments:

  • If abort is uncommented: nothing is printed and the destructor of someobject will not be called.

  • If abort is commented like above: someobject destructor will be called you will get the following output:

exit function 2
exit function 1

Brian R. Bondy
Here, it called exit function 2 THEN exit function 1. gcc 4, Linux 2.6.
strager
Man page for atexit says: "Functions [registered using atexit] are called in reverse order; no arguments are passed."
strager
@strager is right, the functions registered by atexit are supposed to be called in reverse order when either exit is called or main returns.
Robert Gamble
Ran a test and it appears the destructors to global instances are called after all atexit callbacks.
strager
+14  A: 

abort exits your program without calling functions registered using atexit first, and without calling objects' destructors first. exit does both before exiting your program. It does not call destructors for automatic objects though. So

A a;
void test() { 
    static A b;
    A c;
    exit(0);
}

Will destruct a and b properly, but will not call destructors of c. abort will not call destructors of neither objects. As this is unfortunate, the C++ Standard describes an alternative mechanism which ensures properly termination:

Objects with automatic storage duration are all destroyed in a program whose function main() contains no automatic objects and executes the call to exit(). Control can be transferred directly to such a main() by throwing an exception that is caught in main().

struct exit_exception { 
   int c; 
   exit_exception(int c):c(c) { } 
};

int main() {
    try {
        // put all code in here
    } catch(exit_exception& e) {
        exit(e.c);
    }
}

Instead of calling exit, arrange that code throw exit_exception(exit_code); instead.

Johannes Schaub - litb
+1 because, while Brian R. Bondy was good, you did raise the problem of abort/exit (not destructor of stack objects called), and offered the alternative for a RAII-intensive C++ process.
paercebal
I was looking on a way to quit a program without calling dtor and your answer is just what i was looking for! Thanks
acemtp
That is perfectly correct of course, if it actually matters that your automatic objects destructors are not called :-)
Chris Huang-Leaver
This would be a good application for a function-try-block.
Potatoswatter
+1  A: 

abort sends the SIGABRT signal. abort does not return to the caller. The default handler for the SIGABRT signal closes the application. stdio file streams are flushed, then closed. Destructors for C++ class instances are not, however (not sure on this one -- perhaps results are undefined?).

exit has its own callbacks, set with atexit. If callbacks are specified (or only one), they are called in the order reverse of their registration order (like a stack), then the program exits. As with abort, exit does not return to the caller. stdio file streams are flushed, then closed. Also, destructors for C++ class instances are called.

strager
exit can have multiple callback functions registered via atexit, when exit is called all the callback functions will be called in the reverse order in which they were registered.
Robert Gamble
@Gamble, Of course, I mentioned that myself a few minutes ago in a comment to @Bondy's answer. I'll edit my own answer to reflect that.
strager
A: 

From the exit() manual page:

The exit() function causes normal process termination and the value of status & 0377 is returned to the parent.

From the abort() manual page:

The abort() first unblocks the SIGABRT signal, and then raises that signal for the calling process. This results in the abnormal termination of the process unless the SIGABRT signal is caught and the signal handler does not return.

Federico Ramponi
+2  A: 

The following things happen when a program calls exit():

  • Functions registered by the atexit function are executed
  • All open streams are flushed and closed, files created by tmpfile are removed
  • The program terminates with the specified exit code to the host

The abort() function sends the SIGABRT signal to the current process, if it is not caught the program is terminated with no guarantee that open streams are flushed/closed or that temporary files created via tmpfile are removed, atexit registered functions are not called, and a non-zero exit status is returned to the host.

Robert Gamble
hmm. the standard says the program is only not terminated if the signal handler "does not return". you're quite well with C. can you imagine any scenario that would make it allow continue normal execution without returning? i imagine longjmp, but i'm not sure about how it behaves in signal handlers.
Johannes Schaub - litb
In general, calling longjmp from a signal handler is undefined but there is a special case for when the signal was generated with raise/abort so I guess this would be theoretically possible although I don't think I have ever seen it done. Now I am going to have to try it ;)
Robert Gamble
This seems to work (broken into multiple posts due to 300 char limit):#include <stdio.h>#include <stdlib.h>#include <signal.h>#include <setjmp.h>volatile sig_atomic_t do_abort = 1;jmp_buf env;void abort_handler(int i) { do_abort = 0; longjmp(env, 1);}
Robert Gamble
int main(void){ setjmp(env); puts("At setjmp"); if (do_abort) { signal(SIGABRT, abort_handler); puts("Calling abort"); abort(); } puts("Didn't abort!"); return 0;}
Robert Gamble
On Ubuntu 7.04 this prints:At setjmpCalling abortAt setjmpDidn't abort!
Robert Gamble
thanks mate, very nice :)
Johannes Schaub - litb
i've seen it even support longjmp out of a SIGSEGV :) http://libsigsegv.sourceforge.net/
Johannes Schaub - litb
Quantum7