æšæºã®ä»¥åã®ããŒãžã§ã³ãããäŸå€ãã¹ããŒïŒã¹ããŒïŒããã¡ã«ããºã ããããäŸå€ãåŠçããŠããããšã確èªãïŒstd :: uncaught_exceptionïŒãäŸå€ãåŠçãããªãã£ãå Žåã®åæ¢ã¡ã«ããºã ããããŸããã std ::äŸå€ã¯ã©ã¹ã«åºã¥ãæšæºäŸå€ã®éå±€ããããŸãã
æ°ããæšæºã¯ããããã®ãã®ã«ããã€ãã®ãšã³ãã£ãã£ãè¿œå ããŸããããã¯ãç§ã®æèŠã§ã¯ãC ++ã®äŸå€ã䜿çšããŠäœæ¥ãå€§å¹ ã«ç°¡çŽ åã§ããŸãã
exception_ptr
ãããã£ãŠãæåã«ééããå¯èœæ§ãããã®ã¯std :: exception_ptrã§ãã ãã®ã¿ã€ãã䜿çšãããšã絶察ã«ããããã¿ã€ãã®äŸå€ãä¿åã§ããŸãã æšæºã§ã¯ããã®ã¿ã€ãã®ååŸæ¹æ³ã¯æå®ãããŠããŸããã typedefã§ããã¯ã©ã¹ã®å®è£ ã§ãããŸããŸããã ãã®åäœã¯ãstd :: shared_ptrã®åäœã«äŒŒãŠããŸããã€ãŸããã³ããŒããããšãããã©ã¡ãŒã¿ãŒãšããŠæž¡ãããšãã§ããŸãããäŸå€èªäœã¯ã³ããŒãããŸããã exception_ptrã®äž»ãªç®çã¯ãäŸå€ãé¢æ°ãã©ã¡ãŒã¿ãŒãšããŠéä¿¡ããããšã§ã;ã¹ã¬ããéã§äŸå€ãæž¡ãããšãå¯èœã§ãã ãããã£ãŠããã®ã¿ã€ãã®ãªããžã§ã¯ãã¯ãšã©ãŒåŠçãããæè»ã«ããŸãïŒ
struct some_exception { explicit some_exception(int x): v(x) { std::cout << " int ctor" << std::endl; } some_exception(const some_exception & e): v(ev) { std::cout << " copy ctor" << std::endl; } int v; }; std::exception_ptr throwExceptionAndCaptureExceptionPtr() { std::exception_ptr currentException; try { const int throwValue = 10; std::cout << "throwing " << throwValue << "..." << std::endl; throw some_exception(throwValue); } catch (...) { currentException = std::current_exception(); } return currentException; } void rethrowException(std::exception_ptr ePtr) { try { if (ePtr) { std::rethrow_exception(ePtr); } } catch (const some_exception & e) { std::cout << "catched int value: " << ev << std::endl; } std::exception_ptr anotherExceptionPtr = ePtr; try { if (anotherExceptionPtr) { std::rethrow_exception(anotherExceptionPtr); } } catch (const some_exception & e) { std::cout << "catched int value: " << ev << std::endl; } } void checkMakeExceptionPtr() { std::exception_ptr currentException = std::make_exception_ptr(some_exception(20)); std::cout << "exception_ptr constructed" << std::endl; rethrowException(currentException); } void exceptionPtrSample() { rethrowException(throwExceptionAndCaptureExceptionPtr()); checkMakeExceptionPtr(); }
exceptionPtrSampleé¢æ°ãå®è¡ããŠå®è¡ãããšã次ã®ãããªãã®ã衚瀺ãããŸãã
10ãæãã...
int ctor
ãã£ãããããintå€ïŒ10
ãã£ãããããintå€ïŒ10
int ctor
ã³ããŒä¿³åª
ã³ããŒä¿³åª
exception_ptrãæ§ç¯ãããŸãã
ãã£ãããããintå€ïŒ20
ãã£ãããããintå€ïŒ20
exception_ptrã䟿å©ã«äœ¿çšã§ããããã«ããããã«ãããã€ãã®è£å©é¢æ°ããããŸãã
- current_exception-ãã®é¢æ°ã¯exception_ptrãè¿ããŸãã catchãããã¯å ã«ããå Žåãexception_ptrãè¿ããŸããããã«ã¯ãçŸåšã®ã¹ã¬ããã§çŸåšåŠçãããŠããäŸå€ãå«ãŸããŸããcatchãããã¯å€ã§åŒã³åºããšã空ã®exception_ptrãªããžã§ã¯ããè¿ãããŸãã
- rethrow_exception-ãã®é¢æ°ã¯ãexception_ptrã«å«ãŸããäŸå€ãã¹ããŒããŸãã å ¥åãã©ã¡ãŒã¿ãŒã«äŸå€ïŒç©ºã®ãªããžã§ã¯ãïŒãå«ãŸããŠããªãå Žåãçµæã¯æªå®çŸ©ã§ãã ãã®å Žåãmsvcã¯std :: bad_exceptionãã¹ããŒããgcc-4.7.2ã§ã³ã³ãã€ã«ãããããã°ã©ã ã¯äºæããçµäºããŸã ã
- make_exception_ptr-ãã®é¢æ°ã¯ãäŸå€ãã¹ããŒããã«exception_ptrãæ§ç¯ã§ããŸãã ãã®ç®çã¯ãé¢æ°std :: make_shared-ãªããžã§ã¯ãã®æ§ç¯ã«äŒŒãŠããŸãã ãã®å®è¡ã¯ãé¢æ°throwExceptionAndCaptureExceptionPtrã«äŒŒãŠããŸãã gcc-4.7.2ã®å®è£ ã§ã¯ãmake_exception_ptrã¯some_exceptionãªããžã§ã¯ãã®ã³ããŒã2ã€äœæããŸãã
ã¹ã¬ããéã§äŸå€ãæž¡ã
exception_ptråã¯ãã¹ã¬ããéã§äŸå€ãæž¡ãåé¡ã解決ããããã«ç¹å¥ã«äœæãããããã«æããã®ã§ãããã¹ã¬ããããå¥ã®ã¹ã¬ããã«äŸå€ãæž¡ãæ¹æ³ãèããŠã¿ãŸãããã
void worker(std::promise<void> & p) { try { throw std::runtime_error("exception from thread"); } catch (...) { p.set_exception(std::current_exception()); } } void checkThreadAndException() { std::promise<void> p; auto result = p.get_future(); std::thread t(worker, ref(p)); t.detach(); try { result.get(); } catch (const std::runtime_error & e) { std::cout << "runtime error catched from async worker" << std::endl; } }
äžè¬ã«ãC ++ 11ã®ãã«ãã¹ã¬ããã¯åºç¯ãªãããã¯ã§ãããç¬èªã®åŸ®åŠãããã¥ã¢ã³ã¹ããããåå¥ã«èšè¿°ããå¿ èŠããããŸãã äŸå€ãæž¡ãããã ãã«ããã®äŸãèŠãŠã¿ãŸãããã ã¯ãŒã«ãŒé¢æ°ãå¥ã®ã¹ã¬ããã§å®è¡ãããšããã®é¢æ°ã¯äŸå€ãã¹ããŒããŸãã promiseã¯ã©ã¹ã®ãªããžã§ã¯ãã䜿çšãããšãç°ãªãã¹ã¬ããéã®éä¿¡ãæŽçããããã¹ã¬ããããå¥ã®ã¹ã¬ããïŒãŸãã¯äŸå€ïŒã«ã¢ãããã¯ã«å€ã転éã§ããŸãã ãã®äŸã§ã¯ã set_exceptionã¡ãœããã䜿çšããŠããŸãããããã¯ãã©ã¡ãŒã¿ãŒãšããŠexception_ptrãåããŸãã å€ãååŸããããã«ã å°æ¥ã®ã¯ã©ã¹ã®ãªããžã§ã¯ããäœæããŸã-ãããçµæã§ããã getã¡ãœãããåŒã³åºããŸãã ãªããžã§ã¯ãtããã¹ãã©ã¯ã¿ã§ç Žæ£ããããšãjoinableïŒïŒ== falseã§ããããšã確èªããããããã¹ããªãŒã ã§detachãŸãã¯joinã¡ãœãããåŒã³åºãå¿ èŠããããŸããããã§ãªãå Žåã¯ãstd :: terminateãåŒã³åºãããŸãã ã»ãšãã©ã®å Žåãããã¯ããã°ã©ããŒããã¹ã¬ããã解æŸãããã®ã§ã¯ãªããåžžã«ãããã«åŸãïŒãŸãã¯detachã¡ãœããã䜿çšããŠæ瀺çã«è§£æŸããïŒããã§ãã
ãããšã¯å¥ã«ãgcc-4.7ã§ã®ãã«ãã¹ã¬ããã®äœ¿çšã«ã€ããŠèšåãã䟡å€ããããŸãã æåã¯ããã®äŸã¯ç§ã«ãšã£ãŠã¯æ©èœããŸããã§ããïŒäŸå€ãã¹ããŒããŸãïŒãã°ãŒã°ã«ã§ãstd :: threadã䜿çšããã«ã¯-pthreadãã©ã°ããªã³ã«ãŒã«æž¡ãå¿ èŠãããããšãããããŸããã ç§ã¯CMakeããã«ãã·ã¹ãã ãšããŠäœ¿çšããŠããããããã®ã¿ã¹ã¯ã¯åçŽåãããŠããŸãïŒç°ãªããã©ãããã©ãŒã ã§gccã䜿çšããå Žåãããšãã°sparc solarisã§-threadãã©ã°ã䜿çšãããšè€éã«ãªãå ŽåããããŸãïŒ-ãã®åé¡ã解決ããç¹å¥ãªThreads CMakeã¢ãžã¥ãŒã«ããããŸãïŒ
find_packageïŒå¿ èŠãªã¹ã¬ããïŒ
ïŒ...
target_link_librariesïŒcxx_exceptions $ {CMAKE_THREAD_LIBS_INIT}ïŒ
å ¥ãåã®äŸå€
ååã瀺ãããã«ããã®ã¡ã«ããºã ã䜿çšãããšãã¹ããŒãããäŸå€ã«ä»ã®äŸå€ïŒä»¥åã«ã¹ããŒãããå¯èœæ§ãããïŒããä»å ãã§ããŸãã ããšãã°ãç¬èªã®äŸå€ã®éå±€ãããå Žåããã¹ãŠã®ããµãŒãããŒãã£ãäŸå€ããã£ããããããããäŸå€ã«æ·»ä»ããäŸå€ãåŠçãããšãã«è¿œå ãå°åºã§ããŸãã ãããã«ãæ·»ä»ããããŠããæ å ±ïŒããšãã°ããããã°äžã«ããµãŒãããŒãã£ã®äŸå€ã«é¢ããæ å ±ãåºåã§ããŸãïŒã ãã¹ããããäŸå€ã䜿çšããè¯ãäŸãcppreference.comã«ãããŸããç§ã®äŸã¯éšåçã«éè€ããŠããŸãïŒ
struct third_party_exception { explicit third_party_exception(int e) : code(e) { } int code; }; void third_party_worker() { throw third_party_exception(100); } class our_exception : public std::runtime_error { public: our_exception(const std::string & e) : std::runtime_error("our error: " + e) { } }; void ourWorker() { try { third_party_worker(); } catch (...) { throw_with_nested(our_exception("worker failed")); } } void exceptionHandler(const our_exception & e, bool catchNested) { std::cerr << "our exception catched: " << e.what(); if (catchNested) { try { rethrow_if_nested(e); } catch (const third_party_exception & e) { std::cerr << ", low level reason is: " << e.code; } } std::cerr << std::endl; } void exceptionProcessing() { try { ourWorker(); } catch (const our_exception & e) { exceptionHandler(e, false); } try { ourWorker(); } catch (const our_exception & e) { exceptionHandler(e, true); } }
ãã®ãããäŸå€ãã¹ããŒãããµãŒãããŒãã£é¢æ°ããããããµãŒãããŒãã£ãäŸå€ããã£ããããã¢ããã¿ãäœæã§ããŸããã¢ããã¿ã®1ã€ã¯ãäŸå€ããäœæããŸããthird_party_workerãšourWorkerã¯ããããããµãŒãããŒãã£ãé¢æ°ãšãç§ãã¡ãé¢æ°ãšããŠæ©èœããŸãã ãã¹ãŠã®äŸå€ããã£ããããïŒour_exceptionïŒäŸå€ãã¹ããŒãããšåæã«ãããã€ãã®ïŒååãšããŠãã©ã®ãµãŒãããŒãã£ã®äŸå€ãæ·»ä»ãããŠããããããããªãå ŽåããããŸãïŒã ãã®åŸãç§ãã¡ã¯ãã§ã«äŸå€ã«åãçµãã§ããŸãã ããã«ããäžäœãã¬ãã«ã§äœãèµ·ãã£ãã®ãã«ã€ããŠãã詳现ãªæ å ±ãå¿ èŠãªå Žåã¯ãåžžã«rethrow_if_nestedé¢æ°ãåŒã³åºãããšãã§ããŸãã ãã®é¢æ°ã¯ãããã¯ãããïŒãã¹ããããïŒäŸå€ãã¹ããŒããããã©ãããåæããã¹ããŒãããå Žåããã®ãã¹ããããäŸå€ãã¹ããŒããŸãã exceptionHandleré¢æ°ã¯ããç§ãã¡ã®ãäŸå€ãšããµãŒãããŒãã£ã®äŸå€ã«é¢ããæ å ±ã®åºåãèš±å¯ãŸãã¯çŠæ¢ããè¿œå ã®ãã©ã°ãåãå ¥ããŸãã ããšãã°ãæ§æãã¡ã€ã«ïŒãŸãã¯ã¢ã»ã³ããªã«ãã£ãŠã¯ãªãªãŒã¹ããããã°ïŒããcatchNestedãã©ã¡ãŒã¿ãŒãå¶åŸ¡ããããšã«ããããµãŒãããŒãã£ã®äŸå€ã®åºåãå¶åŸ¡ã§ããŸãã
ãã¹ããããäŸå€ãåŠçããã«ã¯ã1ã€ã®ã¯ã©ã¹ãš2ã€ã®é¢æ°ããããŸãã
- nested_exception-ãã®ã¯ã©ã¹ã¯ã std :: throw_with_nestedé¢æ°ãåŒã³åºããšãã«ã¹ããŒãããªããžã§ã¯ããšãæ··åãããŸãããã®ã¯ã©ã¹ã§ã¯ã nested_ptrã¡ãœããã䜿çšããŠããã¹ããããäŸå€ïŒexception_ptrïŒãè¿ãããšãã§ããŸãã ãŸãããã®ã¯ã©ã¹ã«ã¯ããã¹ããããäŸå€ãã¹ããŒããrethrow_nestedã¡ãœããããããŸã
- throw_with_nested-ãã®ãã³ãã¬ãŒãé¢æ°ã¯ãããã¿ã€ãã®ãªããžã§ã¯ããåãïŒ InputTypeãšåŒã³ãŸãããïŒãstd :: nested_exceptionãšInputTypeã®åå«ã§ãããªããžã§ã¯ããã¹ããŒããŸãïŒgccããã®å®è£ ã§ã¯ãnested_exceptionãšInputTypeããç¶æ¿ãããã³ãã¬ãŒãã¿ã€ãã§ãïŒã ãããã£ãŠãã¿ã€ãã®ãªããžã§ã¯ããšnested_exceptionã¿ã€ãã®ãªããžã§ã¯ãã®äž¡æ¹ããã£ãããããã®åŸã®ã¿nested_ptrã¡ãœãããä»ããŠã¿ã€ããååŸã§ããŸãã
- rethrow_if_nested-ãã®é¢æ°ã¯ããªããžã§ã¯ãã«ãã¹ããããäŸå€ããããã©ãããå€æããããå Žåã¯ã¹ããŒããŸãã å®è£ ã¯dynamic_castã䜿çšããŠç¶æ¿ã決å®ã§ããŸã
ååãšããŠããã¹ããããäŸå€ã¡ã«ããºã ã¯éåžžã«èå³æ·±ããã®ã§ãããå®è£ ã¯éåžžã«ç°¡åã§ãããåè¿°ã®é¢æ°current_exceptionããã³rethrow_exceptionã䜿çšããŠèªåã§è¡ãããšãã§ããŸãã åãgccå®è£ ã§ã¯ã nested_exceptionã¯ã©ã¹ã«ã¯ã current_exceptioné¢æ°ã䜿çšããŠã³ã³ã¹ãã©ã¯ã¿ãŒã§åæåãããã¿ã€ãexception_ptrã® 1ã€ã®ãã£ãŒã«ããå«ãŸãã rethrow_nestedã¡ãœããå®è£ ã¯åã«rethrow_exceptioné¢æ°ãåŒã³åºããŸãã
ä»æ§ãé€ã
ãã®ã¡ã«ããºã ã¯ãæ¡åŒµãããïŒçŸåšã¯å»æ¢ãããïŒthrowïŒïŒã¡ã«ããºã ãšèŠãªãããšãã§ããŸãã 以åã®ããã«ããã®äž»ãªç®çã¯ãé¢æ°ãäŸå€ãã¹ããŒããªãããšãä¿èšŒããããšã§ãïŒä¿èšŒã«éåããå Žåãstd :: terminateãåŒã³åºãããŸãïŒã
ãã®ã¡ã«ããºã ã¯ãå€ãthrowïŒïŒãšåæ§ã«2ã€ã®æ¹æ³ã§äœ¿çšãããŸã
void func() noexcept { //... }
ãããŠãæ°ãã圢åŒã§ïŒ
void func() noexcept(boolean_expression_known_at_compile_time) { //... }
ããã«ãåŒã®å€ãtrueãšããŠèšç®ãããå Žåãé¢æ°ã¯noexceptãšããŠããŒã¯ãããŸãããã以å€ã®å Žåããã®ãããªä¿èšŒã¯ãããŸããã
察å¿ããnoexceptïŒåŒïŒæŒç®åããããŸãããããã³ã³ãã€ã«æã«å®è¡ãããåŒãäŸå€ãã¹ããŒããªãå Žåããã®æŒç®åã¯trueãè¿ããŸãã
void noexceptSample() { cout << "noexcept int(): " << noexcept(int()) << endl; cout << "noexcept vector<int>(): " << noexcept(vector<int>()) << endl; }
gcc-4.7.2ã®ãã®ã³ãŒãã¯ä»¥äžã衚瀺ããŸãã
noexcept intïŒïŒïŒ1
noexcept vector <int>ïŒïŒïŒ0
ããã§ãint intã®ã³ã³ã¹ãã©ã¯ã¿ãŒã¯äŸå€ãã¹ããŒãããvectorã®ã³ã³ã¹ãã©ã¯ã¿ãŒã¯ã¹ããŒã§ããïŒnoexceptãšããŠããŒã¯ãããŠããªãïŒããšãããããŸãã
ããã¯ãã³ãã¬ãŒãã¡ã¿ããã°ã©ãã³ã°ã§äœ¿çšãããšäŸ¿å©ã§ãããã®æŒç®åã䜿çšããŠããã³ãã¬ãŒããã©ã¡ãŒã¿ã«å¿ããŠnoexceptãŸãã¯notãšããŠããŒã¯ã§ãããã³ãã¬ãŒãé¢æ°ãäœæã§ããŸãã
template <typename InputTypeT> void func() noexcept(noexcept(InputTypeT())) { InputTypeT var; /// do smth with var std::cout << "func called, object size: " << sizeof(var) << std::endl; } void noexceptSample() { std::cout << "noexcept int(): " << noexcept(int()) << std::endl; std::cout << "noexcept vector<int>(): " << noexcept(std::vector<int>()) << std::endl << std::endl; /// @note function is not actually called std::cout << "noexcept func<int>: " << noexcept(func<int>()) << std::endl; std::cout << "noexcept func<vector<int>>: " << noexcept(func<std::vector<int>>()) << std::endl; }
ãã®äŸã®åºåïŒ
noexcept intïŒïŒïŒ1
noexcept vector <int>ïŒïŒïŒ0
noexcept func <int>ïŒ1
noexcept func <vector <int >>ïŒ0
ãŸãšã
C ++ 11æšæºã¯ãšã©ãŒåŠçã«å€ãããããããŸããããã¡ãããããã§ã®éèŠãªæ©èœã¯exception_ptrã§ãããä»»æã®äŸå€ãéåžžã®ãªããžã§ã¯ããšããŠæž¡ãæ©èœã§ãïŒé¢æ°ã§ã¯ãã¹ã¬ããéã§äŸå€ãæž¡ããŸãïŒã 以åã¯ããã¹ãŠã®ã¹ã¬ããã§ãã¹ãŠã®äŸå€ã«å¯ŸããŠåå²ããtry ... catchãèšè¿°ããå¿ èŠãããããã®æ©èœã¯try ... catchã³ãŒãã®éãå€§å¹ ã«æå°åããŸããã
ãã¹ããããäŸå€ãäœæããããšãã§ããŸããããååãšããŠãboostã©ã€ãã©ãªã«ã¯boost :: exceptionã¡ã«ããºã ãããããªããžã§ã¯ãã«ä»»æã®ããŒã¿ïŒãšã©ãŒã³ãŒããã¡ãã»ãŒãžãªã©ïŒãæ·»ä»ã§ããŸãããäŸå€å ã§ä»»æã®ããŒã¿ãæž¡ãããšã§ä»ã®åé¡ã解決ããŸãã
æåŸã«ãã³ãŒããäŸå€ãã¹ããŒããªãããšãä¿èšŒããå¿ èŠãããå Žå ãç¹ã«noexceptããããŸã ãç¹ã«ãæšæºã©ã€ãã©ãªã®å€ãã®éšåããã®ã¡ã«ããºã ã䜿çšããŠããŸãã
ãã€ãã®ããã«ããã¹ãŠã®äŸã¯githubã«æçš¿ãããŠããŸã
æŽæ°1.åå空éstdã䜿çšããäŸããåé€ãããæšæºã©ã€ãã©ãªã«å±ããââãšã³ãã£ãã£ãšããã§ãªããšã³ãã£ãã£ã確èªã§ããããã«ãªããŸããã