I'm writing a game in which a number of different conditions can cause a failure, for example an image or shader failed to load, OpenGL failed to get a valid context, etc.
In an ideal world, I'd like to use exit codes in the way I believe was intended for C, i.e. non-zero for failure conditions. However, there are some factors that play into this:
atexit()
is not called, unfortunately for me as my program cleanup is handled hierarchically via a single atexit()
registration in main()
, which I like.What arguments can be made for and against using non-zero exit codes in my situation?
atexit()
functionsContrary to your question, functions registered with atexit()
are still called even when the program attempts to return a non-zero termination status to the host environment. A call to exit()
, or the main()
function returning, will trigger the functions registered with atexit()
, regardless of the value given.
Example:
#include <stdlib.h>
#include <stdio.h>
void print_stuff(void)
{
puts("Stuff");
}
int main(void)
{
atexit(print_stuff);
exit(1);
}
This will print Stuff
, even though 1
is returned.
By the ISO C standard, the functions registered in atexit()
are called after exit()
is called. The following situations are also defined as calling exit()
(and therefore triggering the functions registered with atexit()
):
main()
returning is equivalent to calling exit()
.
After the final thread calls thrd_exit()
, exit(EXIT_SUCCESS)
is called.
The following are possible implementation-defined sources of calling exit()
:
The default signal handler for SIGTERM
.
The default constraint handler before using set_constraint_handler_s()
.
The standard mentions the following situations where exit()
and the calls to functions registered with atexit()
are circumvented:
An unhandled SIGABRT
or a SIGABRT
that finishes being handled by a function registered with signal()
. SIGABRT
can be raised by abort()
.
Calling _Exit()
.
Calling quick_exit()
.
The host environment for your implementation may terminate the program in some situations without calling functions registered with atexit()
, such as after a segfault.
Your choice of exit code shouldn't matter too much for a game. Yes, you won't be relying on a shell script to run your game and report errors to the user. Error feedback is probably more useful in the form of dialog popups, a log, or stderr for systems like Linux.