2012-10-30 17 views
13

在未處理的C++例外,我想打印的事件:我可以從Windows SEH異常中解碼C++異常嗎? (?如果是的話,如何)

  1. C++異常
  2. 堆棧跟蹤的消息(what())。

爲了獲得堆棧跟蹤,我結合使用SetUnhandledExceptionFilterStackWalker庫:

struct FooStackWalker : StackWalker 
{ 
    virtual void OnCallstackEntry(CallstackEntryType, CallstackEntry &entry) override 
    { 
     std::cerr << entry.lineFileName << " (" << entry.lineNumber << "): " << entry.undFullName << std::endl; 
    } 
}; 

LONG WINAPI UnhandledExceptionHandler(LPEXCEPTION_POINTERS pointers) 
{ 
    FooStackWalker walker; 
    walker.ShowCallstack(::GetCurrentThread(), pointers->ContextRecord); 
    ::TerminateProcess(::GetCurrentProcess(), 1); 
} 


int main() 
{ 
    ::SetUnhandledExceptionFilter(UnhandledExceptionHandler); 
} 

我已經得到堆棧跟蹤打印就好了,但現在越來越what是難。

是否有某種方法可以將SEH異常解碼爲C++異常,以便在終止之前調用此成員函數?

+0

你會得到3個ExceptionInformation單詞。第二個是指向異常對象的指針。你沒有希望解釋它,沒有像C++中的反射那樣的東西。 * catch *關鍵字發出的異常過濾器非常重要。 –

+0

@Hans:假如拋出的東西總是來自'std :: exception'(這對許多代碼庫來說都是這樣),那麼它是不是可以被解釋?一旦你有一個'std :: exception',你可以'dynamic_cast'到特定的異常類型,如果需要的話...... –

+0

強制轉換爲* what * exception?這是關鍵。你可能會得到*什麼*。 –

回答

2

爲什麼不使用已經爲您提供異常詳細信息的C++機器?它不是SEH過濾器的專有產品(儘管它不包括SetUnhandledExceptionFilter)。你只需要正確地嵌套處理程序:

int main() 
{ 
    try { 
     return cppexcept_main(); 
    } 
    catch (const std::exception& e) 
    { 
     //use e.what() 
    } 
} 

int cppexcept_main() 
{ 
    __try { 
     return application_main(); 
    } 
    __except(GrabStackTrace(GetExceptionInformation()), EXCEPTION_CONTINUE_SEARCH) { 
     /* never reached due to EXCEPTION_CONTINUE_SEARCH */ 
    } 
} 
2

編輯:我誤解了你的問題。我不能肯定地說C++異常的答案是什麼,但我相當肯定答案是「否」。我不相信有任何方法可以區分由SEH引起的未處理的異常(例如訪問衝突)和未捕獲的C++異常,或者用於區分不同類型的C++異常的任何方式。那匹馬已經離開那個穀倉了。

原文如下答案:


沒有,因爲SEH異常不會有what。這不是std::exceptionThis MSDN example表示當您試圖捕捉SEH異常作爲C++異常時,它只能使用省略號(...catch處理程序捕獲。您可以使用_set_se_translator來定義自己的函數,它將SEH異常轉換爲C++異常,但此時您只是在不同的地方從相同的信息生成自己的what(並且即使如此,我也不知道它是否「 d可以從UnhandledExceptionFilter得到)。

您擁有LPEXCEPTION_POINTERS structure所需的全部信息。如果發生訪問衝突,則pointers->ExceptionRecord->ExceptionCode將是EXCEPTION_ACCESS_VIOLATION(0xC0000005)。如果發生這種情況,那麼您可以檢查NumberParametersExceptionInformation變量以確定它是否是讀取或寫入違規以及試圖訪問的地址。

+0

不,我想做相反的事 - 把一個SEH異常變成一個C++異常。當然,如果SEH異常實際上是一個C++異常(MSVC++似乎使用異常代碼「0xE06D7363」),那麼任何轉換都可以自由地失敗或以其他方式告訴我下地獄(在這種情況下,我不會想要嘗試打印堆棧跟蹤 - 不應該在訪問衝突之後嘗試繼續運行或者其他任何操作)。 –

+0

(應該指出的是,我會很高興在普通的C++'catch'中做這種事情,但是在那個時候堆棧已經解開了,所以打印堆棧的投擲點是不可能的) –

+0

確認0xE06D7363:http ://blogs.msdn.com/b/oldnewthing/archive/2010/07/30/10044061.aspx –

相關問題