【问题标题】:Record call stack and values on breakpoint?在断点上记录调用堆栈和值?
【发布时间】:2013-02-01 06:47:47
【问题描述】:

背景

我正在尝试追踪内存泄漏问题,我知道(从 _CRT_DEBUG_MALLOC 和 MFC 以及 CRT 的泄漏检测)内存泄漏的特定行,但由于此行经常被调用,我不知道知道哪个调用实际泄漏。并且分配编号 + __p__crtBreakAlloc() 没有帮助,因为每次运行的分配编号不同。

无论如何,到目前为止的背景。如果您认为我应该使用其他工具,请发表评论。如果答案集中在实际问题上而不是我的潜在问题上,我将不胜感激,因为我发现这比泄漏本身更有趣(我最终会通过足够多的戳来发现)。

问题

在 WinDbg 中(我很确定它不在 VS 中)是否有可能有一个具有以下属性的断点:

  • 它不会中断。 (所以它是一个“跟踪点”)
  • 命中时,记录调用堆栈(直到一定深度)
  • 它还应该记录一些全局状态(变量,可能只是内存地址的原始值)

这可能吗?怎么样?

【问题讨论】:

  • 您所描述的内容听起来像是一种非常低效的泄漏定位方法。您是否尝试过使用UMDH tool?您可以使用 UMDH 轻松获取泄漏分配的调用堆栈。

标签: memory-leaks windbg breakpoints visual-studio-debugging callstack


【解决方案1】:

回答每个问题点:

  • 断点不中断:

    bp myDll!<namespace>::myClass::myFunc "gc" - 你可以执行用双引号分隔的命令,这种情况下,当断点被命中时,继续

  • 在遇到断点时将调用堆栈向上转储一定深度

    .kframes 0n50; bp myDll!<namespace>::myClass::myFunc "kb;gc" - 这将调用堆栈长度设置为 50(默认为 20),0n 告诉它我们是基于十进制的。 bp 之后的双引号中的命令将转储调用堆栈然后继续

  • 记录一些全局状态

    dt myVar - 将显示全局变量,另外将使用d* myVar

    dd myGlobalVar

    确保 pdbs 没有剥离私有符号 - 您应该检查 dt 的信息,因为有特定的开关来处理 unicode 字符串、深度等。此外,您可以在 @ 的监视窗口中轻松观察值987654322@,另请参阅有关d*的文档

WinDbg 中还有一个自动泄漏检测命令:

!heap -l

但我有时会发现它有点受欢迎,更多信息here

【讨论】:

  • 请注意,最好使用gc 命令从断点继续,因为如果您手动单步执行并且最后遇到带有g 的断点,它将起作用就像您按 F5 继续正常执行一样。 gc 命令以与断点被击中时相同的方式继续:如果您正在单步执行,则继续单步执行;如果执行正常运行,将继续正常执行。
  • 另外,k 命令可以显示多个帧,所以你不需要先运行.kframes,如果你想看到不同的帧数:@987654340 @
  • @KurtHutchinson 是的,这是真的,但我喜欢从一开始就有一个非常深的调用堆栈,大多数人不知道它默认为 20
  • @KurtHutchinson 是的,这是一个关于更喜欢 gc 而不是 g 的好点,我会更新我的答案,谢谢
【解决方案2】:

您正在尝试的是一种真正的蛮力方法,在处理内存泄漏时几乎没有积极影响 - 至少需要像 UMDH 这样的东西来应对基于堆栈跟踪跟踪泄漏的复杂性。即使您成功进行了一些跟踪,手动处理也可能过于冗长。

有一个通用的调试器扩展来跟踪各种泄漏,如果你走手动路线,这会给你一些影响:domdbg extension

我写了一个帮助 python 脚本,如果你走 UMDH 路径,你可能会发现它很有用 - 它可以帮助你自动拍摄快照,并且在分析跟踪时可以更有效,因为它会缓存符号信息并将跟踪存储在二进制形式(与 UMDH 使用的文本表示相反):pyumdh

【讨论】:

    【解决方案3】:

    还有一个tracer extension可以跟踪任意打开和关闭操作。

    【讨论】:

      猜你喜欢
      • 2021-06-24
      • 1970-01-01
      • 2015-05-29
      • 1970-01-01
      • 2017-03-14
      • 2011-01-18
      • 2014-11-16
      • 2012-11-12
      • 1970-01-01
      相关资源
      最近更新 更多