20

メッセージ ポンプ内で例外がスローされたときに、Windows が黙って例外を食べ、アプリケーションの実行を継続できるという問題があります。たとえば、テスト用の MFC MDI アプリケーションを作成し、OnDraw をオーバーライドしました。

void CTestView::OnDraw(CDC* /*pDC*/)
{
    *(int*)0 = 0; // Crash

    CTestDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    if (!pDoc)
        return;

    // TODO: add draw code for native data here
}

アプリケーションを実行すると厄介なエラー メッセージが表示されることが予想されますが、実際には何も表示されません。プログラムは問題なく動作しているように見えますが、出力ウィンドウを確認すると次のように表示されます。

Test.exe の 0x13929384 での初回例外: 0xC0000005: アクセス違反の書き込み場所 0x00000000。
Test.exe の 0x77c6ee42 での初回例外: 0xC0150010: 非アクティブ化されているアクティブ化コンテキストは、現在の実行スレッドに対してアクティブではありません。

アプリケーション コンテキストの例外が発生する理由はわかっていますが、それが黙って処理されるのはなぜですか? これは、アプリケーションが使用中に重大な問題を抱えている可能性があることを意味しますが、ユーザーが問題を報告することは決してないため、私たちはそれを知ることはありません.

4

7 に答える 7

12

x64 OS で実行している場合は、これに悩まされている可能性があります。

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

または (この場合はあまりありません)、次の可能性があります: http://blogs.msdn.com/b/oldnewthing/archive/2011/01/20/10117963.aspx

于 2011-02-02T13:28:46.207 に答える
11

同様の質問を閲覧した後、私はこの回答に出くわしました: OpenGLはMFCダイアログベースのアプリケーションで例外を抑制します

「わかりました、これについてさらに情報を見つけました。私の場合、WndProc を呼び出して実行制御を与える前に、KiUserCallbackExceptionHandler を例外ハンドラーとしてインストールするのは Windows 7 です。これは ntdll!KiUserCallbackDispatcher によって行われます。これはセキュリティであると思われます。 SEH へのハッキングを防止するために Microsoft が講じた対策。

解決策は、wndproc (または hookproc) を try/except フレームでラップすることです。"

Microsoft にバグ レポートを提出しました。その回答はこちらで確認できます:
http://connect.microsoft.com/VisualStudio/feedback/details/550944/hardware-exceptions-on-x64-machines-are-silently-caught -wndproc メッセージ内

マイクロソフトから:

ご報告ありがとうございます。これは Windows の問題であり、利用可能なホット フィックスがあることがわかりました。必要に応じてインストールできる修正プログラムについては、 http://support.microsoft.com/kb/976038を参照 してください。

于 2010-04-12T14:29:47.697 に答える
4

これと同じ問題が発生しましたが、これは Microsoft のバグの結果であることがわかりました 。 -wndproc メッセージ内

Microsoft から入手可能な修正プログラムがありますが、ターゲット プラットフォームが複数ある場合、展開はやや困難です。

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

これは、動作を説明する主題に関する記事です。

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

問題は基本的に、32 ビット プログラムのハードウェア例外が、コマンドを送信しない限り、64 ビット OS の WndProc ルーチンで暗黙のうちにキャッチされることです。Microsoft には、Vista SP2 を実行している場合に必要な問題に対する修正プログラムがありますが Windows 7 SP1 では必要ありません (SP なしの Win7 についてはわかりません)。

修正プログラムを適用した場合でも、レジストリ キーを設定するかカーネルを呼び出して、WndProc 中にハードウェア例外が発生した場合にプロセスがクラッシュすることを想定して、正しい動作を有効にする必要があります。

上記の PaulBetts リンクによると、これは Windows Server 2003 との下位互換性のために行われました。

プログラムが 64 ビット プログラムの場合、この問題はなくなります。

于 2012-01-10T23:56:15.367 に答える
4

興味のある機能:

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

PS、SetUnhandledExceptionFilter() は、.exe にロードされた他の dll によってオーバーライドされる可能性があることに注意してください。たとえば、flash と nvidia direct3d がこれを行います。これを解決するために、API フックを使用します。

于 2010-04-12T13:08:43.883 に答える
3

後でこれに出くわした人のために、後知恵で答えてください。

これは、Windows http://support.microsoft.com/kb/976038の既知の問題が原因でした。最新であることを確認し、必要に応じてホットパッチをインストールし、アプリケーションを Windows 7 互換としてマークしてください。http://msdn.microsoft.com/en-us/library/dd371711%28v=vs.85%29.aspx

私はこれを例外コード c015000f と c0150010 で見ました。

于 2011-08-05T22:53:34.413 に答える
2

このコード スニペット ( 64 ビット バージョンの Windows で実行されるアプリケーションからスローされる Microsoft の例外は無視されます) を使用して、Windows が例外を無視しないようにすることができます。これをプロセス コードに挿入します。

// 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); 
   }
}

未処理の例外フィルターも追加する必要がある場合があります。フィルターは、最上位catchブロックのような「トップレベルの例外ハンドラー」のように機能します。_EXCEPTION_POINTERS からプログラマー向けの文字列を抽出するには、EXCEPTION_POINTERS 構造体を文字列に変換する関数はありますか? を参照してください。

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

次のようにフィルターを追加します。

::SetUnhandledExceptionFilter(my_filter);

プロセスのすべてのスレッドでそれを行う必要があります。前のスニペットはプロセスごとですが、フィルターはスレッドごとです。

于 2012-11-28T08:34:19.740 に答える
-1

あなたの出力は、Visual Studio を使用しているように見えます...
私の答えを忘れないでください。
通常スローされる例外を指定できます。つまり、Visual Studio が例外をキャッチし、プログラムはアクセス違反が発生した場所で停止します。これは、Debug/Exceptions... メニューで行います。何を有効にするかわからない場合は、すべて有効にしてください...

于 2010-04-12T13:21:01.943 に答える