什么是LogHelp_TerminateOnAssert? 大偏移量起始地址您的问题

问题描述

十年前有类似的question,但没有很好的答案-希望此后一切都变了。

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

我转储了该应用程序,并通过DebugDiag和WinDbg运行了它,但没有发现任何可疑的东西。

所以我的问题:

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

enter image description here

我的代码中唯一的输入是!get_FrameReceived,该线程的堆栈如下:

enter image description here

周期最多的线程的堆栈如下:

enter image description here

解决方法

在发行版本中,所有这些断言都被编译成类似于以下内容的简单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
,

大偏移量

clr.dll!LogHelp_TerminateOnAssert+0x6835

表示该方法的实际执行距离其开始处为0x6835 = 26661字节。方法不太可能那么大。 (正如@blabb指出的,这是一个1字节的方法。)

通常,您会看到当您没有正确设置符号时(就像在链接的原始问题中一样),但是已将其修复。

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

起始地址

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

所以这就是一切开始的地方。您似乎担心这就是一切结局。

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

该线程的实际操作位于列表的顶部,即ZwRemoveIoCompletion,因此它似乎在进行一些IO操作。

您的问题

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

不。这些只是做好事的起点。 GetQueuedCompletionStatus()似乎正在发生一些IO,.NET为您使用IO完成端口(IOCP)。

应用程序是否正在泄漏内存?

您不会从调用堆栈中看出这一点。您可以通过查看一段时间内的内存来说明这一点。

如果网络上的IO过多,网络无法跟上,则.NET队列中可能会有越来越多的项目,因此它可能看起来像内存泄漏

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

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