2

十年前有一个类似的问题,但没有好的答案——希望从那时起事情发生了变化。

我有一个基于 .NET 4.72 的相当多线程的 Winforms 应用程序。我正在使用 Process Explorer Threads 视图查看它,它有很多clr.dll!LogHelp_TerminateOnAssert+0x6835类型调用。我已经设置了符号路径,但它并没有真正为我清除任何东西。

我对应用程序进行了转储,并通过 DebugDiag 和 WinDbg 运行它,并没有看到任何突出的可疑之处。

所以我的问题:

  • 我应该关心大量的 LogHelp_TerminateOnAssert 调用吗?
  • 应用程序是否泄漏内存?
  • 当我在 Visual Studio 中运行应用程序时,是否有过多的异常无法过滤?

在此处输入图像描述

我的代码中唯一的条目是!get_FrameReceived该线程的堆栈如下:

在此处输入图像描述

循环次数最多的线程的堆栈是这样的:

在此处输入图像描述

4

2 回答 2

2

在发布构建时,所有这些断言都被编译成一个简单的 ret 类似于

ifdef ( debug ) { function body here } elseif { ret } endif

所以偏移量这么大的符号是假的

因此您可能需要为该地址加载实际符号以获得合理的调用堆栈

你可以看到 clr 4.0.30319 clr.dll 中函数的大小只有 1 个字节

0:000> x /v /t clr!LogHelp_TerminateOnAssert
pub func   100115a0             0 <NoType> clr!LogHelp_TerminateOnAssert (<no parameter info>)
0:000> .fnent clr!LogHelp_TerminateOnAssert
Debugger function entry 01bad5e0 for:
(100115a0)   clr!RtlUnwindCallback   |  (100115a1)   clr!memset
Exact matches:
    clr!RtlUnwindCallback (void)
    clr!_TlgDefineProvider_annotation__Tlgg_hClrProviderProv (void)

OffStart:  000115a0
ProcSize:  0x1
Prologue:  0x0
Params:    0n0 (0x0 bytes)
Locals:    0n0 (0x0 bytes)
Registers: 0n0
0:000> u clr!LogHelp_TerminateOnAssert l1
clr!RtlUnwindCallback:
100115a0 c3              ret
于 2020-11-05T11:43:13.993 回答
2

大偏移

clr.dll!LogHelp_TerminateOnAssert+0x6835

意味着该方法中的实际执行距离其开头 0x6835 = 26661 个字节。一种方法不太可能有那么大。(正如@blabb 指出的,这是一个 1 字节的方法)。

通常你会看到,当你没有正确设置符号时(比如在链接的原始问题中),但你已经修复了。

微软可能只发布了公共符号clr.dll而不是私有符号。在这种情况下,您只会看到最后一个已知的公共方法。

起始地址

请注意,该列名为“起始地址”。Process Explorer 将显示堆栈上的第一个条目。

所以这就是一切的开始。你似乎担心这就是一切的结束。

注意:一些已知的内部方法如RtlUserThreadStartBaseThreadInitThunk在显示起始地址时将被跳过。否则它们可能看起来都一样。

线程真正在做的是在列表的顶部,即ZwRemoveIoCompletion,所以它似乎在做一些IO操作。

你的问题

我应该关心大量的 LogHelp_TerminateOnAssert 调用吗?

不,这些只是美好事物的起点。GetQueuedCompletionStatus()看起来有一些 IO 正在进行,.NET 为您使用 IO 完成端口 (IOCP) 。

应用程序是否泄漏内存?

您不会从调用堆栈中看出这一点。你可以通过观察一段时间内的记忆来说明这一点。

如果你有太多的网络 IO 进行并且网络跟不上它,.NET 可能有越来越多的项目在队列中,所以它可能看起来像内存泄漏。

当我在 Visual Studio 中运行应用程序时,是否有过多的异常无法过滤?

您也不会从调用堆栈中得知这一点。sxe clr如果您不信任 Visual Studio,您将附加一个调试器(例如 WinDbg)并检查异常(例如)。

于 2020-11-05T14:01:10.773 回答