29

例外コード c0000374 が発生したときにSetUnhandledExceptionFilterに渡した関数が呼び出されないという問題が発生しました。ただし、例外コード c0000005 で問題なく動作します。次に、代わりにAddVectoredExceptionHandlerを使用しようとしましたが、問題はなく、ハンドラー関数が正しく呼び出されました。

APIのバグですか?どこでも SetUnhandledExceptionFilter の代わりに AddVectoredExceptionHandler を使用できますか?

両方の機能は正しく動作します

// Exception code c0000005
int* p1 = NULL;
*p1 = 99;

AddVectoredExceptionHandler のみがこの例外をキャプチャできます。(ランタイム ライブラリに依存しないことを証明するために、手動で例外を発生させましたが、結果は同じです。)

// Exception code c0000374
RaiseException(0xc0000374, 0, 0, NULL);

テストプログラム。

#include <tchar.h>
#include <fstream>
#include <Windows.h>

LONG WINAPI VectoredExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo)
{
    std::ofstream f;
    f.open("VectoredExceptionHandler.txt", std::ios::out | std::ios::trunc);
    f << std::hex << pExceptionInfo->ExceptionRecord->ExceptionCode << std::endl;
    f.close();

    return EXCEPTION_CONTINUE_SEARCH;
}

LONG WINAPI TopLevelExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo)
{
    std::ofstream f;
    f.open("TopLevelExceptionHandler.txt", std::ios::out | std::ios::trunc);
    f << std::hex << pExceptionInfo->ExceptionRecord->ExceptionCode << std::endl;
    f.close();

    return EXCEPTION_CONTINUE_SEARCH;
}


int _tmain(int argc, _TCHAR* argv[])
{
    AddVectoredExceptionHandler(1, VectoredExceptionHandler);
    SetUnhandledExceptionFilter(TopLevelExceptionHandler);

    // Exception code c0000374
    RaiseException(0xc0000374, 0, 0, NULL);     

    // Exception code c0000005
    // int* p1 = NULL;
    // *p1 = 99;        


    return 0;
}
4

2 に答える 2

18

これは、MSVC CRT スタートアップの次のコードが原因で発生します。

    /*
     * Enable app termination when heap corruption is detected on
     * Windows Vista and above. This is a no-op on down-level OS's
     * and enabled by default for 64-bit processes.
     */

    if (!_NoHeapEnableTerminationOnCorruption)
    {
        HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);
    }

無効にしたい場合 (お勧めしませんnohetoc.obj)、プログラムにリンクしてください。

于 2013-10-29T15:51:38.680 に答える
5

例外は実際にはRtlReportCriticalFailure、ヒープの破損が検出されると、ヒープ マネージャーによって呼び出される のソースで直接キャッチされます。この関数に登録された SEH ハンドラはRtlReportException、すぐに を呼び出しますNtTerminateProcess

SEH ハンドラーは意図的に回避されているとしか言えません。ヒープが破損しているため、スタックの内容 (したがって SEH 登録) も疑わしいものです。とにかく、アプリケーションはヒープの破損から合理的に回復することはできません。

于 2013-10-29T12:24:48.203 に答える