Что такое LogHelp_TerminateOnAssert?
Есть аналогичный вопрос десятилетней давности, но на него не было хорошего ответа - надеюсь, с тех пор все изменилось.
У меня довольно многопоточное приложение Winforms на основе .NET 4.72. Я смотрю на него в режиме просмотра потоков в Process Explorer, и в нем много clr.dll!LogHelp_TerminateOnAssert+0x6835вызовов типов. Я установил путь к символам, но он ничего не прояснил для меня.
Я взял дамп приложения и прогнал его через DebugDiag и WinDbg и не заметил ничего подозрительного.
Итак, мои вопросы:
- Должен ли я беспокоиться о большом количестве вызовов LogHelp_TerminateOnAssert?
- У приложения утечка памяти?
- Есть ли у него чрезмерное количество исключений, которые не фильтруются, когда я запускаю приложение в Visual Studio?
Единственная запись из моего кода здесь - !get_FrameReceivedэто стек для этого потока:
Стек для потока с наибольшим количеством циклов выглядит следующим образом:
Ответы
Большие смещения
clr.dll!LogHelp_TerminateOnAssert+0x6835
означает, что фактическое выполнение в этом методе находится на расстоянии 0x6835 = 26661 байт от его начала. Маловероятно, что метод такой большой. (Как указывает @blabb, это 1-байтовый метод).
Обычно вы видите это, когда вы неправильно настроили символы (как в связанном исходном вопросе), но вы это исправили.
Скорее всего, Microsoft выпустила только общедоступные символы, clr.dllа не частные. В этом случае вы увидите только последний известный общедоступный метод.
Начальный адрес
Обратите внимание, что столбец называется «Начальный адрес». Обозреватель процессов покажет первую запись в стеке.
Итак, здесь все начинается. Вы, кажется, обеспокоены тем, что на этом все заканчивается.
Примечание: некоторые известные внутренние методы, такие как RtlUserThreadStartи, BaseThreadInitThunkбудут пропущены при отображении начального адреса. В противном случае они, вероятно, все выглядели бы одинаково.
То, что на самом деле делает поток, находится в верхней части списка, т.е. ZwRemoveIoCompletionкажется, что он выполняет некоторую операцию ввода-вывода.
Ваши вопросы
Должен ли я беспокоиться о большом количестве вызовов LogHelp_TerminateOnAssert?
Нет. Это только отправная точка для чего-то хорошего. В GetQueuedCompletionStatus()Похоже , что есть некоторые IO происходит и .NET использует порты завершения ввода - вывода (IOCP) для вас.
У приложения утечка памяти?
Вы не заметите этого, взглянув на стеки вызовов. Вы можете сказать это, глядя на память с течением времени.
Если у вас слишком много операций ввода-вывода в сети, и сеть не успевает за ним, .NET может иметь все больше и больше элементов в очереди, поэтому это может выглядеть как утечка памяти.
Есть ли у него чрезмерное количество исключений, которые не фильтруются, когда я запускаю приложение в Visual Studio?
Вы бы также не сказали этого из стека вызовов. Вы должны прикрепить отладчик (например, WinDbg) и проверить исключения (например, sxe clr), если вы не доверяете Visual Studio.
при сборке выпуска все эти утверждения компилируются в простой 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