title | description | ms.date | helpviewer_keywords | ||||
---|---|---|---|---|---|---|---|
C++ program termination |
Learn about the standard ways to exit a C++-language program. |
07/07/2022 |
|
In C++, you can exit a program in these ways:
The exit
function, declared in <stdlib.h>, terminates a C++ program. The value supplied as an argument to exit
is returned to the operating system as the program's return code or exit code. By convention, a return code of zero means that the program completed successfully. You can use the constants EXIT_FAILURE
and EXIT_SUCCESS
, also defined in <stdlib.h>, to indicate success or failure of your program.
The abort
function, also declared in the standard include file <stdlib.h>, terminates a C++ program. The difference between exit
and abort
is that exit
allows the C++ runtime termination processing to take place (global object destructors get called). abort
terminates the program immediately. The abort
function bypasses the normal destruction process for initialized global static objects. It also bypasses any special processing that was specified using the atexit
function.
Microsoft-specific: For Windows compatibility reasons, the Microsoft implementation of abort
may allow DLL termination code to run in certain circumstances. For more information, see abort
.
Use the atexit
function to specify actions that execute before the program terminates. No global static objects initialized before the call to atexit
are destroyed before execution of the exit-processing function.
The return
statement allows you to specify a return value from main
. A return
statement in main
first acts like any other return
statement. Any automatic variables are destroyed. Then, main
invokes exit
with the return value as a parameter. Consider the following example:
// return_statement.cpp
#include <stdlib.h>
struct S
{
int value;
};
int main()
{
S s{ 3 };
exit( 3 );
// or
return 3;
}
The exit
and return
statements in the preceding example have similar behavior. Both terminate the program and return a value of 3 to the operating system. The difference is that exit
doesn't destroy the automatic variable s
, while the return
statement does.
Normally, C++ requires that functions that have return types other than void
return a value. The main
function is an exception; it can end without a return
statement. In that case, it returns an implementation-specific value to the invoking process. (By default, MSVC returns 0.)
When you call exit
directly (or when it's called after a return
statement from main
), thread objects associated with the current thread are destroyed. Next, static objects are destroyed in the reverse order of their initialization (after calls to functions specified to atexit
, if any). The following example shows how such initialization and cleanup works.
In the following example, the static objects sd1
and sd2
are created and initialized before entry to main
. After this program terminates using the return
statement, first sd2
is destroyed and then sd1
. The destructor for the ShowData
class closes the files associated with these static objects.
// using_exit_or_return1.cpp
#include <stdio.h>
class ShowData {
public:
// Constructor opens a file.
ShowData( const char *szDev ) {
errno_t err;
err = fopen_s(&OutputDev, szDev, "w" );
}
// Destructor closes the file.
~ShowData() { fclose( OutputDev ); }
// Disp function shows a string on the output device.
void Disp( char *szData ) {
fputs( szData, OutputDev );
}
private:
FILE *OutputDev;
};
// Define a static object of type ShowData. The output device
// selected is "CON" -- the standard output device.
ShowData sd1 = "CON";
// Define another static object of type ShowData. The output
// is directed to a file called "HELLO.DAT"
ShowData sd2 = "hello.dat";
int main() {
sd1.Disp( "hello to default device\n" );
sd2.Disp( "hello to file hello.dat\n" );
}
Another way to write this code is to declare the ShowData
objects with block scope, which implicitly destroys them when they go out of scope:
int main() {
ShowData sd1( "CON" ), sd2( "hello.dat" );
sd1.Disp( "hello to default device\n" );
sd2.Disp( "hello to file hello.dat\n" );
}