Exceptions silently caught by Windows, how to handle manually?

前端 未结 7 1244
一整个雨季
一整个雨季 2020-12-13 14:45

We\'re having problems with Windows silently eating exceptions and allowing the application to continue running, when the exception is thrown inside the message pump. For ex

相关标签:
7条回答
  • 2020-12-13 15:09

    functions that may be of interest:

    SetUnhandledExceptionFilter()
    _set_invalid_parameter_handler()
    _RTC_SetErrorFuncW()
    _CrtSetReportHookW2()
    

    PS, be aware that SetUnhandledExceptionFilter() can be overriden by other dlls loaded into your .exe. eg, flash and nvidia direct3d do this. I use api hooking to cure this.

    0 讨论(0)
  • 2020-12-13 15:09

    ANSWER IN HINDSIGHT for anyone who stumbles upon this later.

    This was caused by a known issue in Windows http://support.microsoft.com/kb/976038 - make sure you're up to date, install the hotpatch if you need to, and mark your application as Windows 7 compatible. http://msdn.microsoft.com/en-us/library/dd371711%28v=vs.85%29.aspx

    I've seen this with exception codes c015000f and c0150010.

    0 讨论(0)
  • 2020-12-13 15:13

    I experienced this same issue, and found it was a result of this Microsoft bug: http://connect.microsoft.com/VisualStudio/feedback/details/550944/hardware-exceptions-on-x64-machines-are-silently-caught-in-wndproc-messages

    There’s a fix available from Microsoft, though deploying it is somewhat challenging if you have multiple target platforms:

    http://support.microsoft.com/kb/976038

    Here's an article on the subject describing the behavior:

    http://blog.paulbetts.org/index.php/2010/07/20/the-case-of-the-disappearing-onload-exception-user-mode-callback-exceptions-in-x64/

    The issue is basically that Hardware exceptions in 32-bit programs are silently caught in the WndProc routine on 64-bit OSs, unless you send commands telling it not to. Microsoft has a hotfix for the issue that is required if you're running Vista SP2, but isn't required with Windows 7 SP1 (not sure about Win7 without the SP).

    Even WITH the hotfix, you need to enable the correct behavior by setting a registry key or making some calls to the kernel to tell it your process expects hardware exceptions to crash when encountered during WndProc.

    According to the PaulBetts link above, this was done for backwards compatibility with Windows Server 2003.

    If you program is a 64-bit program, this issue goes away.

    0 讨论(0)
  • 2020-12-13 15:28

    If you're running on an x64 OS you may have been bitten by this:

    http://blog.paulbetts.org/index.php/2010/07/20/the-case-of-the-disappearing-onload-exception-user-mode-callback-exceptions-in-x64/

    Or (less likely in this case), it may be this: http://blogs.msdn.com/b/oldnewthing/archive/2011/01/20/10117963.aspx

    0 讨论(0)
  • 2020-12-13 15:28

    You can force Windows to not ignore the exceptions with this code snippet (from Microsoft's Exceptions that are thrown from an application that runs in a 64-bit version of Windows are ignored) that you will put in your process code:

    // my SDK is v6.0A and the two APIs are not available in the .h files, so I need to get them at runtime
    #define PROCESS_CALLBACK_FILTER_ENABLED     0x1
    typedef BOOL (WINAPI *GETPROCESSUSERMODEEXCEPTIONPOLICY)(__out LPDWORD lpFlags);
    typedef BOOL (WINAPI *SETPROCESSUSERMODEEXCEPTIONPOLICY)(__in DWORD dwFlags );
    HINSTANCE h = ::LoadLibrary(L"kernel32.dll");
    if ( h ) {
       GETPROCESSUSERMODEEXCEPTIONPOLICY GetProcessUserModeExceptionPolicy = reinterpret_cast< GETPROCESSUSERMODEEXCEPTIONPOLICY >( ::GetProcAddress(h, "GetProcessUserModeExceptionPolicy") );
       SETPROCESSUSERMODEEXCEPTIONPOLICY SetProcessUserModeExceptionPolicy = reinterpret_cast< SETPROCESSUSERMODEEXCEPTIONPOLICY >( ::GetProcAddress(h, "SetProcessUserModeExceptionPolicy") );
       if ( GetProcessUserModeExceptionPolicy == 0 || SetProcessUserModeExceptionPolicy == 0 ) {
          return;
       }
       DWORD dwFlags;
       if (GetProcessUserModeExceptionPolicy(&dwFlags)) {
          SetProcessUserModeExceptionPolicy(dwFlags & ~PROCESS_CALLBACK_FILTER_ENABLED); 
       }
    }
    

    It may be you have to add also an unhandled exception filter: the filter acts like a "top level exception handler" that is like a topmost catch block. For extracting a programmer-friendly string from _EXCEPTION_POINTERS you can see Is there a function to convert EXCEPTION_POINTERS struct to a string?

    LONG WINAPI my_filter(_In_  struct _EXCEPTION_POINTERS *ExceptionInfo)
    {
       ::OutputDebugStringA("an exception occured!");
       return EXCEPTION_EXECUTE_HANDLER;
    }
    

    You add the filter with:

    ::SetUnhandledExceptionFilter(my_filter);
    

    and you have to do it in every threads of your process: while the previous snippet is per-process, the filter is per-thread.

    0 讨论(0)
  • 2020-12-13 15:31

    Your output looks like you're using Visual Studio...
    If not forget about my answer.
    You can specify which exceptions will be thrown normally, meaning that Visual Studio catches them and your progam stops where the access violation occurred. Do this in the Debug/Exceptions... menu. If you are not sure what to enable, just enable them all...

    0 讨论(0)
提交回复
热议问题