1

マネージド (.net/c#) の catch ブロックでネイティブ (c++/win32) でスローした例外に関するデータを受信しようとしています。

たとえば、C++ では次のことができます。

void MyFunc()
{
    const char* data = "my exception info";
    ULONG_PTR args[1] { data };
    RaiseException(0,0,1,args);
}

この関数は、C# から P/Invoke を介して呼び出すことができます。

[DLLImport("MyLib.dll")]
extern public static void MyFunc();

static void Main()
{
    try { MyFunc(); }
    catch(SEHException seh)
    {
        // Where is my exception info? :(
    }
}

SEHExceptionには、インポートされた DLL 関数からの文字列が含まれてません。

SEHException.ErrorCode は常に E_FAIL のように見えますが、いずれにしても int よりも豊富なデータをマーシャリングしたいと考えています。

何か不足していますか、または例外を介してこの文字列データを取得する別の方法はありますか?

目的は、SetUnhandledExceptionFilter のようなネイティブ フィルターを設定することにより、ネイティブ スタック トレースでネイティブ例外を再発生させることです。参考までに。

4

1 に答える 1

1

通常、SEH 例外には引数がなく、データの邪魔になるものはほとんどありません。実際に取得できるのは、数値の例外コード、例外が発生したときのプロセッサの状態 (命令ポインターとスタック ポインターを含む)だけです。

C++ 例外処理で使用されるのは、ハンドラーを起動するために使用される SEH 例外ですが、C++ 例外オブジェクトは実際には別の場所に格納されています (詳細はコンパイラとそのランタイム ライブラリの内部にあります)。他の言語からアクセスすることはほぼ不可能です。他の C++ コンパイラでさえ、ひどい時間を過ごしています。すべての C++ 例外は、1 つの例外コードを共有します。

RaiseExceptionあなたがやっているように、手動で呼び出すと、OS の例外EXCEPTION_ACCESS_VIOLATIONと同じように例外パラメーターを保存できます。MSDNEXCEPTION_IN_PAGE_ERRORを参照してください。Microsoft C++ コンパイラを使用すると、. また、C++ オブジェクトを のように結合するべきではありません。C++ コンパイラがこれらのオブジェクトの有効期間を管理するために追加する追加の魔法が欠けていることになります。ただし、文字列データを文字列リテラルとして渡すことは問題ないはずです..EXCEPTION_RECORDGetExceptionInformationstd::stringRaiseExceptionconst char*

次に、この情報を .NET で取得するという問題に直面します。SEHExceptionこの限られた (例外コード、コンテキスト、レコード、C++ オブジェクトは含まれない) 情報でさえ、.NETオブジェクトからは取得できないと思います。あなたが見ている理由E_FAILは、例外コードではなく、ドキュメントのこのメモの結果です。

SEHException クラスは、アンマネージ コードからスローされたが、別の .NET Framework 例外にマップされていない SEH エラーを処理します。SEHException クラスは、値が 0x80004005 の HRESULT E_FAIL にも応答します。

于 2014-09-03T17:50:29.123 に答える