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 thetmpfile
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 theexit
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 theabort
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 byfunc
, 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.
Python exit commands - why so many and when should each be used?
The functions* quit()
, exit()
, and sys.exit()
function in the same way: they raise the SystemExit
exception. So there is no real difference, except that sys.exit()
is always available but exit()
and quit()
are only available if the site
module is imported (docs).
The os._exit()
function is special, it exits immediately without calling any cleanup functions (it doesn't flush buffers, for example). This is designed for highly specialized use cases... basically, only in the child after an os.fork()
call.
Conclusion
Use
exit()
orquit()
in the REPL.Use
sys.exit()
in scripts, orraise SystemExit()
if you prefer.Use
os._exit()
for child processes to exit after a call toos.fork()
.
All of these can be called without arguments, or you can specify the exit status, e.g., exit(1)
or raise SystemExit(1)
to exit with status 1. Note that portable programs are limited to exit status codes in the range 0-255, if you raise SystemExit(256)
on many systems this will get truncated and your process will actually exit with status 0.
Footnotes
* Actually, quit()
and exit()
are callable instance objects, but I think it's okay to call them functions.
Is there a way to run an expression on.exit() but only if completes normally, not on error?
Just wrap the args of all your return function calls with the code that you want done. So your example becomes:
foo = function(thing){do something; return(thing)}
myfunction = function() {
...
if (...) then return( foo(point 1) )
...
if (...) then return( foo(point 2) )
...
if (...) then return( foo(point 3) )
...
return ( foo(point 4) )
}
Or just make each then
clause into two statements. Using on.exit
to lever some code into a number of places is going to cause spooky action-at-a-distance problems and make the baby Dijkstra cry (read Dijkstra's "GOTO considered harmful" paper).
R: on.exit - use returned value without knowing its name
Since R 3.2.0 it is fully possible, thanks to new function returnValue
.
Working example below.
f <- function(x, err = FALSE){
pt <- proc.time()[[3L]]
on.exit(message(paste("proc.time:",round(proc.time()[[3L]]-pt,4),"\nnrow:",as.integer(nrow(returnValue()))[1L])))
Sys.sleep(0.001)
if(err) stop("some error")
return(x)
}
dt <- data.frame(a = 1:5, b = letters[1:5])
f(dt)
f(dt, err=T)
f(dt)
f(dt[dt$a %in% 2:3 & dt$b %in% c("c","d"),])
Example of on.exit, add argument
Here is a very simple example
myfun <- function(x){
on.exit(print("first"))
on.exit(print("second"), add = TRUE)
return(x)
}
myfun(2)
#[1] "first"
#[1] "second"
#[1] 2
Also note what happens without the add=TRUE parameter
fun <- function(x){
on.exit(print("first"))
on.exit(print("second"))
return(x)
}
fun(2)
#[1] "second"
#[1] 2
The second call to on.exit removes the first call if you don't add the "add=TRUE".
Should I end my PHP script with exit or exit;?
exit
, exit;
, exit()
, and exit();
are exactly the same, but the fact is that you should not end your script with an exit() call, it's just bad practice (but it works).
EDIT
Clarifying why i said it's "bad practice", it's not about the functionality of "exit" itself, it's OK to halt the script execution if something bad happens, but the concept of "something bad" is really wide. In general, even if some unwanted condition occurs, the normal execution flow should reach to the end of the file. Just consider this example:
...some init stuff...
if (!user_is_authenticated) {
...print some nasty message...
exit();
}
...continue with normal stuff...
A better approach would be:
...some init stuff...
if (user_is_authenticated) {
...continue with normal stuff...
}
else {
...print some nasty message...
}
What's the difference? The difference is that in the second version you don't need to use exit(), which means if one day you need to do something after BOTH the "normal" and "unwanted" execution flows you can just add it at the end of the file.
It's more or less the same argument about why you should NOT use "return" in function bodies except at the end of the function..
Related Topics
Unique Elements of Two Vectors
How to Change the Default Font Size in Ggplot2
More Efficient Means of Creating a Corpus and Dtm with 4M Rows
Knitr: Run All Chunks in an Rmarkdown Document
Using R and Plot.Ly - How to Script Saving My Output as a Webpage
Find the Most Frequently Occuring Words in a Text in R
For Each Group Summarise Means for All Variables in Dataframe (Ddply? Split)
Partial Animal String Matching in R
Overlaying Two Graphs Using Ggplot2 in R
Installing Rmysql in Mavericks
Shiny Doesn't Show Me the Entire Selectinput When I Have Choices > 1000
Effectively Debugging Shiny Apps
How to Identify the Distribution of the Given Data Using R
HTML with Multicolumn Table in Markdown Using Knitr
Adding Lagged Variables to an Lm Model
How to Know If R Is Running on 64 Bits Versus 32