How to end C++ code -
i c++ code stop running if condition met, i'm not sure how that. @ point if if
statement true terminate code this:
if (x==1) { kill code; }
there several ways, first need understand why object cleanup important, , hence reason std::exit
marginalized among c++ programmers.
raii , stack unwinding
c++ makes use of idiom called raii, in simple terms means objects should perform initialization in constructor , cleanup in destructor. instance std::ofstream
class [may] open file during constructor, user performs output operations on it, , @ end of life cycle, determined scope, destructor called closes file , flushes written content disk.
what happens if don't destructor flush , close file? who knows! possibly won't write data supposed write file.
for instance consider code
#include <fstream> #include <exception> #include <memory> void inner_mad() { throw std::exception(); } void mad() { std::unique_ptr<int> ptr(new int); inner_mad(); } int main() { std::ofstream os("file.txt"); os << "content!!!"; int possibility = /* either 1, 2, 3 or 4 */; if(possibility == 1) return 0; else if(possibility == 2) throw std::exception(); else if(possibility == 3) mad(); else if(possibility == 4) exit(0); }
what happens in each possibility is:
- possibility 1: return leaves current function scope, knows end of life cycle of
os
calling destructor , doing proper cleanup closing , flushing file disk. - possibility 2: throwing exception takes care of life cycle of objects in current scope, doing proper cleanup...
- possibility 3: here stack unwinding enters in action! though exception thrown @
inner_mad
, unwinder go though stack ofmad
,main
perform proper cleanup, objects going destructed properly, includingptr
,os
. - possibility 4: well, here?
exit
c function , it's not aware nor compatible c++ idioms. does not perform cleanup on objects, includingos
in same scope. file won't closed , reason content might never written it! - other possibilities: it'll leave main scope, performing implicit
return 0
, having same effect possibility 1, i.e. proper cleanup.
but don't told (mainly possibilities 2 , 3); continue reading , we'll find out how perform proper exception based cleanup.
possible ways end
return main!
you should whenever possible; prefer return program returning proper exit status main.
the caller of program, , possibly operating system, might want know whether program supposed done or not. same reason should return either 0 or exit_success
signal program terminated , exit_failure
signal program terminated unsuccessfully, other form of return value implementation-defined (§18.5/8).
however may deep in call stack, , returning of may painful...
[do not] throw exception
throwing exception perform proper object cleanup using stack unwinding, calling destructor of every object in previous scope.
but here's the catch! it's implementation-defined whether stack unwinding performed when thrown exception not handled (by catch(...) clause) or if have noexcept
function in middle of call stack. stated in §15.5.1 [except.terminate]:
in situations exception handling must abandoned less subtle error handling techniques. [note: these situations are:
[...]
— when exception handling mechanism cannot find handler thrown exception (15.3), or when search handler (15.3) encounters outermost block of function
noexcept
-specification not allow exception (15.4), or [...][...]
in such cases, std::terminate() called (18.8.3). in situation no matching handler found, implementation-defined whether or not stack unwound before std::terminate() called [...]
so have catch it!
do throw exception , catch @ main!
since uncaught exceptions may not perform stack unwinding (and consequently won't perform proper cleanup), should catch exception in main , return exit status (exit_success
or exit_failure
).
so possibly setup be:
int main() { /* ... */ try { // insert code return throwing exception. } catch(const std::exception&) // consider using custom exception type intentional { // throws. idea might `return_exception`. return exit_failure; } /* ... */ }
[do not] std::exit
this not perform sort of stack unwinding, , no alive object on stack call respective destructor perform cleanup.
this enforced in §3.6.1/4 [basic.start.init]:
terminating program without leaving current block (e.g., calling function std::exit(int) (18.5)) not destroy objects automatic storage duration (12.4). if std::exit called end program during destruction of object static or thread storage duration, program has undefined behavior.
think now, why such thing? how many objects have painfully damaged?
other [as bad] alternatives
there other ways terminate program (other crashing), aren't recommended. sake of clarification going presented here. notice how normal program termination does not mean stack unwinding okay state operating system.
std::_exit
causes normal program termination, , that's it.std::quick_exit
causes normal program termination , callsstd::at_quick_exit
handlers, no other cleanup performed.std::exit
causes normal program termination , callsstd::atexit
handlers. other sorts of cleanups performed such calling static objects destructors.std::abort
causes abnormal program termination, no cleanup performed. should called if program terminated in really, unexpected way. it'll nothing signal os abnormal termination. systems perform core dump in case.std::terminate
callsstd::terminate_handler
callsstd::abort
default.
Comments
Post a Comment