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
oscalling 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,mainperform proper cleanup, objects going destructed properly, includingptr,os. - possibility 4: well, here?
exitc function , it's not aware nor compatible c++ idioms. does not perform cleanup on objects, includingosin 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::_exitcauses normal program termination, , that's it.std::quick_exitcauses normal program termination , callsstd::at_quick_exithandlers, no other cleanup performed.std::exitcauses normal program termination , callsstd::atexithandlers. other sorts of cleanups performed such calling static objects destructors.std::abortcauses 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::terminatecallsstd::terminate_handlercallsstd::abortdefault.
Comments
Post a Comment