AFX_EXCEPTION_LINK::AFX_EXCEPTION_LINK() { // setup initial link state m_pException = NULL; // no current exception yet // wire into top of exception link stack AFX_EXCEPTION_CONTEXT* pContext = AfxGetExceptionContext(); m_pLinkPrev = pContext->m_pLinkTop; pContext->m_pLinkTop = this; }
// out-of-line implementation of CATCH and AND_CATCH BOOL AFXAPI AfxCatchProc(CRuntimeClass* pClass) { ASSERT(pClass != NULL); AFX_EXCEPTION_CONTEXT* pContext = AfxGetExceptionContext(); ASSERT(pContext->m_pLinkTop != NULL); CException* pException = pContext->m_pLinkTop->m_pException; ASSERT(pException != NULL); return pException->IsKindOf(pClass); }
// out-of-line implementation of THROW (for non-C++ exceptions) void AFXAPI AfxThrow(CException* pNewException) { // get current exception context for running task AFX_EXCEPTION_CONTEXT* pContext = AfxGetExceptionContext(); // check for THROW_LAST() first if (pNewException == NULL) { ASSERT(pContext->m_pLinkTop != NULL); pNewException = pContext->m_pLinkTop->m_pException; } ASSERT_VALID(pNewException); TRACE1("Warning: Throwing an Exception of type %hs.\n", pNewException->GetRuntimeClass()->m_lpszClassName); while (pContext->m_pLinkTop != NULL) { AFX_EXCEPTION_LINK* pReceiver = pContext->m_pLinkTop; if (pReceiver->m_pException != NULL) { // a THROW during a CATCH block -- this link may not be // destructed, so it is necessary to do all the cleanup that // the destructor would do. if (pReceiver->m_pException != pNewException) pReceiver->m_pException->Delete(); pReceiver->m_pException = NULL; pContext->m_pLinkTop = pReceiver->m_pLinkPrev; } else { // throw the exception to the top handler (if appropriate type) if (pReceiver->m_nType == 0) { // setup the receiver's context for the new exception pReceiver->m_pException = pNewException; // and jump into the handler... longjmp(pReceiver->m_jumpBuf, 1); ASSERT(FALSE); // not reached } // otherwise just call cleanup proc (*pReceiver->m_callback.pfnCleanup)(pReceiver); } } ASSERT(pContext->m_pLinkTop == NULL); // uncaught exception, terminate TRACE1("Error: Uncaught Exception (%hs).\n", pNewException->GetRuntimeClass()->m_lpszClassName); AfxTerminate(); ASSERT(FALSE); // not reached }
// out-of-line cleanup called from inline AFX_EXCEPTION_LINK destructor void AFXAPI AfxTryCleanup() { AFX_EXCEPTION_CONTEXT* pContext = AfxGetExceptionContext(); AFX_EXCEPTION_LINK* pLinkTop = pContext->m_pLinkTop; // delete current exception ASSERT(pLinkTop != NULL); if (pLinkTop->m_pException != NULL) pLinkTop->m_pException->Delete(); // remove ourself from the top of the chain pContext->m_pLinkTop = pLinkTop->m_pLinkPrev; }
// special out-of-line implementation of THROW_LAST (for auto-delete behavior) void AFXAPI AfxThrowLastCleanup() { AFX_EXCEPTION_CONTEXT* pContext = AfxGetExceptionContext(); AFX_EXCEPTION_LINK* pLinkTop = pContext->m_pLinkTop; // check for THROW_LAST inside of auto-delete block if (pLinkTop != NULL) { // make sure current exception does not get auto-deleted pLinkTop->m_pException = NULL; } // THROW_LAST macro will do actual 'throw' }