2013-10-29 14 views
19

例外コードc0000374が発生したときに私がSetUnhandledExceptionFilterに渡した関数が呼び出されなかったという問題が発生しました。しかし、それは例外コードc0000005で正常に動作します。 代わりにAddVectoredExceptionHandlerを使用しようとしましたが、問題はなく、ハンドラ関数が正しく呼び出されます。SetUnhandledExceptionFilterがいくつかの例外をキャプチャできないのに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

名前の違いは、 'SetUnhandledExceptionFilter'は未処理の例外に対してのみ呼び出される点です。 C++ランタイムライブラリが内部的に他の例外の型を処理する可能性を考えましたか? – hvd

+0

@hvdそれは可能だと思います。私は検証する方法を見つけるでしょう。 – wrongite

答えて

4

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

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

+1

アプリケーションがヒープの破損から復旧できないことがあります。しかし、診断目的のために、ミニダンプを書くことは非常に価値があります。さらに、64ビットのビルドでは、いずれにせよテーブルベースの例外処理(フレームベース)が使用されるため、破損したヒープやスタックは例外処理に影響しません。私はあなたの推論に従わない:あなたは* "SEHハンドラーが意図的に回避されている"と結論するために、例外ハンドラーにコードを追従させた*。それは意味をなさない。 – IInspectable

11

それは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をリンクします。

関連する問題