VS2005中SetUnhandledExceptionFilter函式應用
很多軟體通過設定自己的異常捕獲函式,捕獲未處理的異常,生成報告或者日誌(例如生成mini-dump檔案),達到Release版本下追蹤Bug的目的。但是,到了VS2005(即VC8),Microsoft對CRT(C執行時庫)的一些與安全相關的程式碼做了些改動,典型的,例如增加了對緩衝溢位的檢查。新CRT版本在出現錯誤時強制把異常拋給預設的偵錯程式(如果沒有配置的話,預設是Dr.Watson),而不再通知應用程式設定的異常捕獲函式,這種行為主要在以下三種情況出現。
(1) 呼叫abort函式,並且設定了_CALL_REPORTFAULT選項(這個選項在Release版本是預設設定的)。
(2) 啟用了執行時安全檢查選項,並且在軟體執行時檢查出安全性錯誤,例如出現快取溢位。(安全檢查選項/GS 預設也是開啟的)
(3) 遇到_invalid_parameter錯誤,而應用程式又沒有主動呼叫
_set_invalid_parameter_handler設定錯誤捕獲函式。
所以結論是,使用VS2005(VC8)編譯的程式,許多錯誤都不能在SetUnhandledExceptionFilter捕獲到。這是CRT相對於前面版本的一個比較大的改變,但是很遺憾,Microsoft卻沒有在相應的文件明確指出。
解決方法
之所以應用程式捕獲不到那些異常,原因是因為新版本的CRT實現在異常處理中強制刪除所有應用程式先前設定的捕獲函式,如下所示:
/* Make sure any filter already in place is deleted. */
SetUnhandledExceptionFilter(NULL);
UnhandledExceptionFilter(&ExceptionPointers);
解決方法是攔截CRT呼叫SetUnhandledExceptionFilter函式,使之無效。在X86平臺下,可以使用以下程式碼。
#ifndef _M_IX86
#error “The following code only works for x86!”
#endif
void DisableSetUnhandledExceptionFilter()
{
void *addr = (void*)GetProcAddress(LoadLibrary(_T(“kernel32.dll”)),
“SetUnhandledExceptionFilter”);
if (addr)
{
unsigned char code[16];
int size = 0;
code[size++] = 0x33;
code[size++] = 0xC0;
code[size++] = 0xC2;
code[size++] = 0x04;
code[size++] = 0x00;
DWORD dwOldFlag, dwTempFlag;
VirtualProtect(addr, size, PAGE_READWRITE, &dwOldFlag);
WriteProcessMemory(GetCurrentProcess(), addr, code, size, NULL);
VirtualProtect(addr, size, dwOldFlag, &dwTempFlag);
}
}
在設定自己的異常處理函式後,呼叫DisableSetUnhandledExceptionFilter禁止CRT設定即可。
其它討論
上面通過設定api hook,解決了在VS2005上的異常捕獲問題,這種雖然不是那麼“乾淨”的解決方案,確是目前唯一簡單有效的方式。
雖然也可以通過_set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT), signal(SIGABRT, …),和_set_invalid_parameter_handler(…) 解決(1)(3),但是對於(2),設定api hook是唯一的方式。
相關文章
- zip函式在爬蟲中應用函式爬蟲
- Render函式在Vue多頁面應用中的應用函式Vue
- iOS中round/ceil/floorf函式的應用iOS函式
- Excel中Text 函式應用技巧集錦Excel函式
- 類中靜態回撥函式應用函式
- gethostbyname函式和getservbyname函式的應用函式
- 如何在 Deno 應用程式中呼叫 Rust 函式Rust函式
- 小程式開發中雲函式的應用!函式
- MySQL 日期函式、時間函式在實際場景中的應用MySql函式
- Hash函式及其應用函式
- Vue函式式元件的應用Vue函式元件
- 函式柯里化和偏函式應用函式
- 三角函式在前端動畫中的應用函式前端動畫
- Excel函式應用教程:函式的引數(轉)Excel函式
- Java 函式式介面 lamada 應用Java函式
- Generator函式非同步應用函式非同步
- 函式計算——應用初探函式
- 函式進階應用3函式
- SetUnhandledExceptionFilter 的討論ExceptionFilter
- Excel函式應用教程:函式的輸入方法(轉)Excel函式
- Excel函式應用教程:函式與公式的概念(轉)Excel函式公式
- javascript高階函式的應用JavaScript函式
- 高階函式應用--currying函式
- pandas.DataFrame.groupby函式應用函式
- Python的sorted函式應用Python函式
- sqlserver拆分字串函式 及應用SQLServer字串函式
- 觀察者模式在One Order回撥函式中的應用模式函式
- python中list列表的高階應用 高階函式Python函式
- R語言中na.omit函式的應用 以及 在資料框中的應用R語言MIT函式
- mysql中的if函式怎麼用MySql函式
- day10-函式的應用函式
- 函式計算-HelloWorld應用開發函式
- 自定義UDF函式應用異常函式
- 應用呼叫驅動的ioctl函式函式
- JavaScript回撥函式應用淺析JavaScript函式
- 分析函式的應用(更新版)函式
- 四個PHP應用小函式 (轉)PHP函式
- PostgreSQL的generate_series函式應用SQL函式