<menu id="w8yyk"><menu id="w8yyk"></menu></menu>
  • <dd id="w8yyk"><nav id="w8yyk"></nav></dd>
    <menu id="w8yyk"></menu>
    <menu id="w8yyk"><code id="w8yyk"></code></menu>
    <menu id="w8yyk"></menu>
    <xmp id="w8yyk">
    <xmp id="w8yyk"><nav id="w8yyk"></nav>
  • 網站首頁 > 物聯資訊 > 技術分享

    VS2005中SetUnhandledExceptionFilter函數應用

    2016-09-28 00:00:00 廣州睿豐德信息科技有限公司 閱讀
    睿豐德科技 專注RFID識別技術和條碼識別技術與管理軟件的集成項目。質量追溯系統、MES系統、金蝶與條碼系統對接、用友與條碼系統對接

    很多軟件通過設置自己的異常捕獲函數,捕獲未處理的異常,生成報告或者日志(例如生成mini-dump文件),達到Release版本下追蹤Bug的目的。但是,到了VS2005(即VC8),MicrosoftCRTC運行時庫)的一些與安全相關的代碼做了些改動,典型的,例如增加了對緩沖溢出的檢查。新CRT版本在出現錯誤時強制把異常拋給默認的調試器(如果沒有配置的話,默認是Dr.Watson),而不再通知應用程序設置的異常捕獲函數,這種行為主要在以下三種情況出現。

    (1)       調用abort函數,并且設置了_CALL_REPORTFAULT選項(這個選項在Release版本是默認設置的)。

    (2)       啟用了運行時安全檢查選項,并且在軟件運行時檢查出安全性錯誤,例如出現緩存溢出。(安全檢查選項/GS 默認也是打開的)

    (3)       遇到_invalid_parameter錯誤,而應用程序又沒有主動調用

    _set_invalid_parameter_handler設置錯誤捕獲函數。

    所以結論是,使用VS2005VC8)編譯的程序,許多錯誤都不能在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是唯一的方式。

    RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成
    最近免费观看高清韩国日本大全