5

起動時に DLL をロードする MFC SDI アプリケーションがあります。ソースコードを表示してDLLを使用することしかできませんが、変更して再コンパイルすることはできません。

現在の状況では、DLL がエラーに遭遇するたびに、以下のように exit() が呼び出されます。

bool Func()
{
  // .. do something here

  if (error) { exit(999); }
}

私の MFC アプリケーションでは、すべての例外を処理するように SetUnhandledExceptionFilter を設定し、デバッグ用に MiniDump も作成しました。

したがって、問題は、DLL がエラーに遭遇するたびに、ステータス コード 999 で exit() を呼び出すだけであり、私の ExceptionFilter はそれをキャッチしないため、PostMortem デバッグ用の MiniDump が作成されないことです。

1. グローバル例外ハンドラーがこれをキャッチする他の方法はありますか
?
2. exit() 関数をオーバーライドして、呼び出されたときに「throw("エラー発生!")」を呼び出し、グローバル例外ハンドラーがそれをキャッチできるようにすることはできますか?
3. MFC アプリケーションで atexit() を使用してみました。これにより、DLL が exit() を呼び出すたびにエラーをスローする別の関数を登録します。しかし、これもうまく機能していないようです。

私が本当にやりたかったことは、DLL でエラーが発生するたびに、MiniDump を生成して PostMortem デバッグを実行できるようにすることです。この状況でうまくいく可能性のあるものは他にありますか?

ありがとう。

4

4 に答える 4

1

DLL のシンボル インポート テーブルを確認してください。

実行時に選択した関数に再マップできる場合があります。

それを行う方法(出口があると仮定):

ほとんどの DLL は、ジャンプ テーブルを介してシンボル インポートを使用します。呼び出し元にブレークポイントを設定すると、ロング ジャンプ命令が呼び出されることがわかります。ジャンプ テーブルは PAGE_EXECUTE_READWRITE ページなので、ジャンプ テーブルのそのスロットを自分のアドレスで上書きするだけです。

ジャンプ テーブルの場所はさまざまですが、常にロード アドレスからの一定のオフセットであるため、GetProcAddress によって検出された DLL への任意の関数ポインターからの一定のオフセットになります。

もちろん、これはすべて、DLL が変更されないことを前提としています。実行時にこれらすべてを見つける方法はおそらくありますが、どうすればよいかわかりません。

ああ、exit() から戻ることはできません。ロングジャンプアウトする必要があります。

于 2009-09-20T15:06:40.613 に答える
0

これに対する解決策はまだ見つかりませんが、ハンドラーが役に立たない理由の 1 つとして考えられるのatexitは、dll が CRT に静的にリンクしている可能性があることです。これは、exit() のコードが dll に直接組み込まれていることを意味します。これにより、終了ハンドラーの独自のプライベート リストが提供されるため、ホスト プロセス内から登録された atexit ハンドラーは表示されません。dll 内から呼び出すことができればatexit()(これを調整するのはかなり難しい)、うまくいく可能性があります。

推測ですが、お役に立てば幸いです。

于 2009-09-20T14:34:57.270 に答える
0

プロセスが正常に終了すると、すべての DLL がDLL_PROCESS_DETACH 通知を受け取ります。この通知をキャッチすることだけを目的として独自の DLL を作成するのはどうですか?

于 2009-11-05T23:32:56.673 に答える
0

exit() 関数にブレークポイントを配置するために作成したマクロを次に示します。

Imports System.IO

' Sets breakpoints on all exit functions.  useful for catching library code that 
' calls exit in the debugger.
Sub AddBreakpointsToExit()
    Dim bp As EnvDTE.Breakpoint
    Dim bps As EnvDTE.Breakpoints

    Dim envVar As String = "VS90COMNTOOLS"
    Dim comnTools As String = System.Environment.GetEnvironmentVariable(envVar)
    If (String.IsNullOrEmpty(comnTools)) Then
        Throw New System.Exception("Environment variable '" + envVar + "' doesn't exist.")
    End If
    Dim filePath As String = System.IO.Path.Combine(comnTools, "..\..\VC\crt\src\crt0dat.c")

    ' set exit function names and line #s:
    Dim exitFunctions(0 To 4) As String
    exitFunctions(0) = "exit"
    exitFunctions(1) = "_exit"
    exitFunctions(2) = "_cexit"
    exitFunctions(3) = "_c_exit"

    ' line numbers are based on the Visual Studio 2008 definition.
    ' TODO: check and add options if 2005 or 2010 are differen.t
    Dim exitLines(0 To 4) As Integer
    exitLines(0) = 412
    exitLines(1) = 420
    exitLines(2) = 427
    exitLines(3) = 434

    ' set breakpoints:
    For i = 0 To 3 Step 1
        bps = DTE.Debugger.Breakpoints.Add(File:=filePath, Line:=exitLines(i))
    Next i

End Sub
于 2009-07-29T17:54:30.213 に答える