如何在WinRT中从C++获取堆栈跟踪?

8

我需要从C++应用程序获取堆栈跟踪,并将其序列化为字符串,以便稍后解析。在Windows上,我听说唯一可用的API是StackWalk64,但它似乎不被支持。

在Windows Store应用程序中,如何从C++获取堆栈跟踪?


1
这是不可能的。C++代码过于优化,无法允许可靠的堆栈跟踪。您可以使用minidumps来诊断C++崩溃。在商店应用程序中很难获得。 - Hans Passant
2
用户可以选择启用Windows在应用程序崩溃时发送崩溃转储。然后您可以在仪表板中查看崩溃转储,以便下载并在调试器中打开它。 - Filip Skakun
在C#代码中也不可能。内联和尾调用将使您的堆栈遍历变得完全不可靠。由于这个原因,GetCallingAssembly及其相关的C#调用已从Windows 8 .NET框架中删除。dbghelp.dll是功能存在的地方,但是,在Windows 8商店应用程序下,它是不受支持的。如果您愿意,请继续请求它,但在我的书中,有一长串更高优先级的事情需要处理 :-) - Kevin Frei
@HansPassant 实际上在 Windows CE(C++ 应用程序)中,我能够获取到在 release 模式下构建的 .exe 文件非常好的堆栈跟踪。我使用映射文件和 GetThreadCallStack 函数。 - marcinj
2个回答

1
以下是适用于我的汇编代码。这仅适用于x86平台,因此仅在模拟器上进行调试时有用。返回的帧指针可用于跳转到源代码的反汇编窗口。我认为可以使用映射文件来获取精确的源代码位置。
我使用此代码查找内存泄漏,与crtdbg结合使用,它在具有大量分配的非常大的应用程序中工作得非常好。VS 2013内存分析器最多可以处理1分钟的数据记录。
  FINLINE static DWORD GetCallerFrameNum(int index) {
#if defined(_DEBUG) && defined(_MSC_VER) && defined(_M_IX86)

    DWORD caller = 0;
    __asm
    {
      mov ebx, ebp
        mov ecx, index
        inc ecx
        xor eax, eax
      StackTrace_getCaller_next :
      mov eax, [ebx + 4]
        mov ebx, [ebx]
        dec ecx
        jnz StackTrace_getCaller_next
        mov caller, eax
    }
    return caller;

#else

    return 0;

#endif
  }

  template<class T>
  void RecordStackTrace(T& vecOut) {
    vecOut.clear();
    vecOut.reserve(32);
    for (INT iInitLevel = 1; iInitLevel < 32; ++iInitLevel) {
      DWORD dwFrameNum = GetCallerFrameNum(iInitLevel);
      if (!dwFrameNum)
        return;
      vecOut.push_back(dwFrameNum);
    }
  }

1
我唯一能够调试复杂WINRT问题的方法是使用ETW来跟踪因果链。虽然设置有点繁琐,但这篇文章(虽然涉及C#)强调了这种方法: 以下是两个不错的介绍ETW用于C/C++的入门文章: 使用此方法,您应该能够创建ETW事件,然后在应用程序中侦听它们,并将它们包含为序列化字符串以供以后分析。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接