Should we use exit() in C?

Rather than abort(), the exit() function in C is considered to be a "graceful" exit.

From C11 (N1570) 7.22.4.4/p2 The exit function (emphasis mine):

The exit function causes normal program termination to occur.

The Standard also says in 7.22.4.4/p4 that:

Next, all open streams with unwritten buffered data are flushed, all open streams are closed, and all files created by the tmpfile function are removed.

It is also worth looking at 7.21.3/p5 Files:

If the main function returns to its original caller, or if the exit function is called, all open files are closed (hence all output streams are flushed) before program termination. Other paths to program termination, such as calling the abort function, need not close all files properly.

However, as mentioned in comments below you can't assume that it will cover every other resource, so you may need to resort to atexit() and define callbacks for their release individually. In fact it is exactly what atexit() is intended to do, as it says in 7.22.4.2/p2 The atexit function:

The atexit function registers the function pointed to by func, to be called without arguments at normal program termination.

Notably, the C standard does not say precisely what should happen to objects of allocated storage duration (i.e. malloc()), thus requiring you be aware of how it is done on particular implementation. For modern, host-oriented OS it is likely that the system will take care of it, but still you might want to handle this by yourself in order to silence memory debuggers such as Valgrind.


Yes, it is ok to use exit in C.

To ensure all buffers and graceful orderly shutdown, it would be recommended to use this function atexit, more information on this here

An example code would be like this:

void cleanup(void){
   /* example of closing file pointer and free up memory */
   if (fp) fclose(fp);
   if (ptr) free(ptr);
}

int main(int argc, char **argv){
   /* ... */
   atexit(cleanup);
   /* ... */
   return 0;
}

Now, whenever exit is called, the function cleanup will get executed, which can house graceful shutdown, clean up of buffers, memory etc.


You don't have constructors and destructors but you could have resources (e.g. files, streams, sockets) and it is important to close them correctly. A buffer could not be written synchronously, so exiting from the program without correctly closing the resource first, could lead to corruption.