6

如果我使用类似于此处描述的类/方法,如何在堆栈顶部获取调用的描述/地址?

基本上我想要一些可以在调用我们的错误跟踪系统时使用的值。我想根据导致异常的指令的地址“唯一”识别。

(通常是 mydll.dll!1234ABDC() 的形式)

编辑:

一些背景资料:

我正在创建一个小型转储以通过电子邮件发送到缺陷跟踪系统 (fogbugz)。为了减少重复,我试图为崩溃想出一个合理的“签名”。我知道 FB 有一个 xml PI,但它需要用户登录,我们还不确定我们能否负担得起让人们嗅探我们的流量并获取用户信息的费用。电子邮件现在也更容易实现。稍后我们将使用 XML API 来提交 minidump。

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发送到的结构TopLevelFilter()包含一个EXCEPTION_RECORD结构,该结构包含ExceptionAddress. 通过使用CreateToolhelp32Snapshot枚举模块,您可以找出违规操作码在哪个 DLL 中的地址。您还可以使用函数 indbghelp.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 回答
0

您可以通过保存 minidump 并使用 cdb.exe 或 windbg.exe 提取异常来避免为异常打印字符串的痛苦(如果您可以保存 minidump 但无法格式化字符串而不崩溃,会发生什么情况?)信息。

于 2010-03-02T00:22:55.390 回答