c++ Òì³£´¦Àí£¨1£©(¶þ)
ÂëÖÐдÏÂ"throw xxx"ʱ£¬±àÒëÆ÷»á·ÖÅäÒ»¸ö½á¹¹À´±íʾ¸ÃÒì³££¬¸ÃÒì³£ÓÐÒ»¸öÍ·²¿£¬¶¨ÒåÈçÏ£º
¸´ÖÆ´úÂë
struct __cxa_exception
{
std::type_info * exceptionType;
void (*exceptionDestructor) (void *);
unexpected_handler unexpectedHandler;
terminate_handler terminateHandler;
__cxa_exception * nextException;
int handlerCount;
int handlerSwitchValue;
const char * actionRecord;
const char * languageSpecificData;
void * catchTemp;
void * adjustedPtr;
_Unwind_Exception unwindHeader;
};
¸´ÖÆ´úÂë
×¢ÒâÆäÖÐ×îºóÒ»¸ö±äÁ¿£º_Unwind_Exception unwindHeader£¬¾ÍÊÇÇ°ÃæItanium½Ó¿ÚÀïÌáµ½µÄ½Ó¿ÚÄÚ²¿ÓõĽṹÌå¡£µ±Óû§throwÒ»¸öÒ쳣ʱ£¬±àÒëÆ÷»á°ïÎÒÃǵ÷ÓÃÏàÓ¦µÄº¯Êý·ÖÅä³öÈçÏÂÒ»¸ö½á¹¹£º
ÆäÖÐ_cxa_exception¾ÍÊÇÍ·²¿£¬exception_objÔòÊÇ"throw xxx"ÖеÄxxx£¬ÕâÁ½²¿·ÖÔÚÄÚ´æÖÐÊÇÁ¬ÐøµÄ¡£
Òì³£¶ÔÏóÓɺ¯Êý__cxa_allocate_exception()½øÐд´½¨£¬×îºóÓÉ__cxa_free_exception()½øÐÐÏú»Ù¡£
µ±ÎÒÃÇÔÚ³ÌÐòÀïÖ´ÐÐÁËÅ׳öÒì³£ºó£¬±àÒëÆ÷ΪÎÒÃÇ×öÁËÈçϵÄÊÂÇ飺
1£©µ÷ÓÃ__cxa_allocate_exceptionº¯Êý£¬·ÖÅäÒ»¸öÒì³£¶ÔÏó¡£
2£©µ÷ÓÃ__cxa_throwº¯Êý£¬Õâ¸öº¯Êý»á½«ÉÏÃæ·ÖÅäµÄÒì³£¶ÔÏó×öһЩ³õʼ»¯¡£
3£©__cxa_throw() »á±»ÓÃItanium ABIÀïµÄ_Unwind_RaiseException()´Ó¶ø¿ªÊ¼unwind.
4) ÕÒµ½¶ÔÓ¦µÄcatch´úÂ룬µ÷ÓÃ__cxa_begin_catch()
5) Ö´ÐÐcatchÖеĴúÂë¡£
6£©µ÷ÓÃ__cxa_end_catch().
7) µ÷ÓÃ_Unwind_Resume().
´Óc++µÄ½Ç¶È¿´£¬Ò»¸öÍêÕûµÄÒì³£´¦ÀíÁ÷³Ì¾ÍÍê³ÉÁË£¬µ±È»£¬ÆäÖÐÊ¡ÂÔÁ˺ܶàµÄϸ½Ú¡£
UnwindµÄ¹ý³Ì
unwindµÄ¹ý³ÌÊÇ´Ó__cxa_throw()À↑ʼµÄ£¬Çë¿´ÈçÏÂÔ´Â룺
¸´ÖÆ´úÂë
extern "C" void
__cxxabiv1::__cxa_throw (void *obj, std::type_info *tinfo,
void (_GLIBCXX_CDTOR_CALLABI *dest) (void *))
{
PROBE2 (throw, obj, tinfo);
// Definitely a primary.
__cxa_refcounted_exception *header = __get_refcounted_exception_header_from_obj (obj);
header->referenceCount = 1;
header->exc.exceptionType = tinfo;
header->exc.exceptionDestructor = dest;
header->exc.unexpectedHandler = std::get_unexpected ();
header->exc.terminateHandler = std::get_terminate ();
__GXX_INIT_PRIMARY_EXCEPTION_CLASS(header->exc.unwindHeader.exception_class);
header->exc.unwindHeader.exception_cleanup = __gxx_exception_cleanup;
#ifdef _GLIBCXX_SJLJ_EXCEPTIONS
_Unwind_SjLj_RaiseException (&header->exc.unwindHeader);
#else
_Unwind_RaiseException (&header->exc.unwindHeader);
#endif
// Some sort of unwinding error. Note that terminate is a handler.
__cxa_begin_catch (&header->exc.unwindHeader);
std::terminate ();
}
¸´ÖÆ´úÂë
ÈçÇ°ÃæËù˵£¬unwind·ÖΪÁ½¸ö½×¶Î£¬Ò»¸öÓÃÀ´ËÑË÷catch£¬Ò»¸öÓÃÀ´ÇåÀíµ÷ÓÃÕ»£º
¸´ÖÆ´úÂë
/* Raise an exception, passing along the given exception object. */
_Unwind_Reason_Code
_Unwind_RaiseException(struct _Unwind_Exception *exc)
{
struct _Unwind_Context this_context, cur_context;
_Unwind_Reason_Code code;
uw_init_context (&this_context);
cur_context = this_context;
/* Phase 1: Search. Unwind the stack, calling the personality routine
with the _UA_SEARCH_PHASE flag set. Do not modify the stack yet. */
while (1)
{
_Unwind_FrameState fs;
code = uw_frame_state_for (&cur_context, &fs);
if (code == _URC_END_OF_STACK)
/* Hit end of stack with no handler found. */
return _URC_END_OF_STACK;
if (code != _URC_NO_REASON)
/* Some error encountered. Ususally the unwinder doesn't
diagnose these and merely crashes. */