void ExtException::AddMoreMessages(const Exception * E) { if (E != nullptr) { if (FMoreMessages == nullptr) { FMoreMessages = new TStringList(); } const ExtException * ExtE = dyn_cast<ExtException>(E); if (ExtE != nullptr) { if (ExtE->GetMoreMessages() != nullptr) { FMoreMessages->Assign(ExtE->GetMoreMessages()); } } UnicodeString Msg; ExceptionMessageFormatted(E, Msg); // new exception does not have own message, this is in fact duplication of // the exception data, but the exception class may being changed if (Message.IsEmpty()) { Message = Msg; } else if (!Msg.IsEmpty()) { FMoreMessages->Insert(0, UnformatMessage(Msg)); } if (IsInternalException(E)) { AppendExceptionStackTraceAndForget(FMoreMessages); } if (FMoreMessages->GetCount() == 0) { SAFE_DESTROY(FMoreMessages); } } }
//--------------------------------------------------------------------------- static void __fastcall DoExceptNotify(TObject * ExceptObj, void * ExceptAddr, bool OSException, void * BaseOfStack) { if (ExceptObj != NULL) { Exception * E = dynamic_cast<Exception *>(ExceptObj); if ((E != NULL) && IsInternalException(E)) // optimization { DoExceptionStackTrace(ExceptObj, ExceptAddr, OSException, BaseOfStack); TJclStackInfoList * StackInfoList = JclLastExceptStackList(); if (ALWAYS_TRUE(StackInfoList != NULL)) { std::unique_ptr<TStrings> StackTrace(StackInfoListToStrings(StackInfoList)); DWORD ThreadID = GetCurrentThreadId(); TGuard Guard(StackTraceCriticalSection.get()); TStackTraceMap::iterator Iterator = StackTraceMap.find(ThreadID); if (Iterator != StackTraceMap.end()) { Iterator->second->Add(L""); Iterator->second->AddStrings(StackTrace.get()); } else { StackTraceMap.insert(std::make_pair(ThreadID, StackTrace.release())); } // this chains so that JclLastExceptStackList() returns NULL the next time // for the current thread delete StackInfoList; } } } }
Exception * CloneException(Exception * E) { Exception * Result; // this list has to be in sync with ExceptionMessage ExtException * Ext = dyn_cast<ExtException>(E); if (Ext != nullptr) { Result = Ext->Clone(); } else if (isa<ECallbackGuardAbort>(E)) { Result = new ECallbackGuardAbort(); } else if (isa<EAbort>(E)) { Result = new EAbort(E->Message); } else if (WellKnownException(E, nullptr, nullptr, &Result, false)) { // noop } else { // we do not expect this to happen if (DebugAlwaysFalse(IsInternalException(E))) { // to save exception stack trace Result = ExtException::CloneFrom(E); } else { Result = new Exception(E->Message); } } return Result; }
Exception * CloneException(Exception * E) { Exception * Result; // this list has to be in sync with ExceptionMessage ExtException * Ext = NB_STATIC_DOWNCAST(ExtException, E); if (Ext != nullptr) { Result = Ext->Clone(); } else if (NB_STATIC_DOWNCAST(ECallbackGuardAbort, E) != nullptr) { Result = new ECallbackGuardAbort(); } else if (NB_STATIC_DOWNCAST(EAbort, E) != nullptr) { Result = new EAbort(E->Message); } else if (WellKnownException(E, nullptr, nullptr, &Result, false)) { // noop } else { // we do not expect this to happen if (ALWAYS_FALSE(IsInternalException(E))) { // to save exception stack trace Result = ExtException::CloneFrom(E); } else { Result = new Exception(E->Message); } } return Result; }