6

ここで説明されているようなクラス/メソッドを使用する場合、スタックの一番上にある呼び出しの説明/アドレスを取得するにはどうすればよいですか?

基本的に、バグ追跡システムへの呼び出しで使用できる何らかの値が必要です。例外の原因となった命令のアドレスに基づいて「一意に」識別したい。

(通常、mydll.dll!1234ABDC() のような形式です)

編集:

背景情報:

欠陥追跡システム (fogbugz) に電子メールで送信するためのミニダンプを作成しています。重複を減らすために、クラッシュの妥当な「署名」を見つけようとしています。FB 用の xml PI があることは知っていますが、これにはユーザー ログオンが必要であり、トラフィックを傍受してユーザー情報を取得する余裕があるかどうかはまだわかりません。メール送信も今のところ実装が簡単です。後で、XML API を使用してミニダンプを送信します。

4

4 に答える 4

4

これを行うためのコードを例外フィルターに配置する必要があります。例外ハンドラーに到達するまでに、例外のコンテキスト情報の多くが失われています。

try 
{
  // whatever
}
except (MyExceptionFilter(GetExceptionInformation()))
{
}

フィルタは次のようになります

LONG WINAPI MyExceptionFilter (
   EXCEPTION_POINTERS * pExcept,
   BOOL                 fPassOn)
{
   EXCEPTION_RECORD * pER = pExcept->ExceptionRecord;
   DWORD dwExceptionCode = pER->ExceptionCode;

   TCHAR szOut[MAX_PATH*4]; // exception output goes here.
   szOut[0] = 0;

   MEMORY_BASIC_INFORMATION mbi;
   DWORD cb = VirtualQuery (pER->ExceptionAddress, &mbi, sizeof(mbi));
   if (cb == sizeof(mbi))
      {
      TCHAR szModule[MAX_PATH];
      if (GetModuleFileName ((HMODULE)mbi.AllocationBase, szModule, MAX_PATH))
         {
         wsprintf(szOut, "Exception at '%s' + 0x%X", szModule, 
                  (ULONG_PTR)pER->ExceptionAddress - (ULONG_PTR)mbi.AllocationBase);
         }
      }

   return EXCEPTION_EXECUTE_HANDLER;
}

もちろん、64ビットアーキテクチャでは出力を少し調整する必要があります。その場合、ExceptionAddressとAllocationBaseは64ビット量になるためです。

于 2010-03-01T22:27:01.197 に答える
1

EXCEPTION_POINTERS送信される構造体には、. CreateToolhelp32Snapshotを使用してモジュールを列挙することにより、問題のあるオペコードがどの DLL にあるかを特定できるこのアドレス。の関数を使用して、アドレスに対応するシンボルを見つけることもできます (それが入っている関数)TopLevelFilter()EXCEPTION_RECORDExceptionAddressdbghelp.dll

于 2010-03-01T22:01:25.257 に答える
1

GetExceptionInformation は、例外に関する情報を含む EXCEPTION_POINTERS 構造体を返します。ExceptionRecord メンバーには、例外のアドレスである ExceptionAddress メンバーが含まれています。

このアドレスを、コード内のモジュールの相対位置にマッピングして有効にする必要があります。GetModuleHandleEx を GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS と共に使用して、HMODULE (モジュールのベース アドレスでもあります) を取得できます。次に、GetModuleInformation を使用して、例外が発生したモジュールの実際の名前を取得できます。

障害が実際にシステム DLL 内にある場合、これは役に立たないかもしれません。より洗練されたスキームは、(dbghelp で Stackwalk64 を使用して) スタック トレースを生成し、コードにない最上位のフレームを無視することです。

于 2010-03-01T22:03:20.627 に答える