2

未処理の例外をキャッチしてダンプを作成するように設計されたエラー処理コードがあります。

さて、ネイティブコードとマネージコードの間の移行でこれがうまく機能しないいくつかの状況に遭遇しました。

たとえば、Paint()イベントでネイティブコードを呼び出すと、そのネイティブコードが例外をスローします。
メッセージループディスパッチャは、ネイティブ例外をキャッチしてから、.NETを再スローしますSEHException
COMオブジェクトをホストするDLLでも同じことが起こることがあります。

これに伴う問題は、スタックのロールバックと、SEHExceptionネイティブ例外からのをキャッチして作成する方法のために、実際のネイティブ呼び出しスタックが破壊されることです。

?を使用して、どういうわけかネイティブコールスタックを取得できますSEHExceptionか?(SEHExceptionのコールスタックはCLRコールスタックであることに注意してください)。

または、アプリケーションを設定して、コールスタックを何らかの方法で保存することはできますか?

4

2 に答える 2

1

何が起こるかというと、ウィンドウをペイントする必要があるときに.Netが呼び出されます。 どうやら.Netはこれを非常に安全にし、追加の予防措置とエラー処理を追加しました。 Paint()

今、私のPaint()イベントは、ネイティブC++ dllを呼び出すC++/CLIラッパーdllを呼び出しました。ネイティブC++例外により、アクセス違反例外が発生しました。

これで、.Netがその例外をキャッチし、それを管理SEHException対象オブジェクトとしてラップしました。実際のエラーポイントからすべての呼び出しスタックが失われました。

解決:

.Net例外処理の前に、例外をキャッチする必要があります。
通常の例外処理フローはネット上にありますが、このサイトは実際のフローの良い例を示しています。例外ハンドラー

.Netは例外をキャッチし、SetUnhandledExceptionFilterハンドラーが呼び出される前にそれらをラップしているようです。

AddVectoredExceptionHandlerそこで、エラーコードをチェックして致命的な例外をチェックするファーストチャンス例外ハンドラーを追加しました。

//SEH exceptions have code 0xC0000xxxx
#define SEH_TYPE (DWORD)0xC0000000L 
//mask the last byte
#define SEH_MASK (DWORD)0xFF000000L 
    LONG WINAPI CheckForSEHException( struct _EXCEPTION_POINTERS *lpTopLevelExceptionFilter)
    {   
        if ((lpTopLevelExceptionFilter->ExceptionRecord->ExceptionCode & SEH_MASK) == SEH_TYPE) //mask and check the last bits if it's an SEH exception
        {
            //handle exception here (create a dump or something)
            return EXCEPTION_EXECUTE_HANDLER;
        }
        return EXCEPTION_CONTINUE_SEARCH;
    }

例外コードはWinBase.hにあり、定義に従って実際のエラーコードを確認できます。(つまり、探しますEXCEPTION_ACCESS_VIOLATION

于 2012-05-23T11:40:54.363 に答える
1

!dumpheap-typeSEHExceptionを試してください。SEHExceptionのアドレスを使用して、例外の!peアドレスを出力します。コールスタックを取得します

于 2012-05-02T21:19:30.647 に答える