Co to jest LogHelp_TerminateOnAssert?
Jest podobne pytanie sprzed dekady, ale nie było dobrej odpowiedzi - miejmy nadzieję, że od tego czasu sytuacja się zmieniła.
Mam dość wielowątkową aplikację Winforms opartą na .NET 4.72. Patrzę na to z widokiem wątków Process Explorer i ma wiele clr.dll!LogHelp_TerminateOnAssert+0x6835wywołań typów. Skonfigurowałem ścieżkę symboli, ale tak naprawdę niczego mi to nie wyjaśniło.
Zrobiłem zrzut aplikacji i przepuściłem go przez DebugDiag i WinDbg i nie widziałem nic podejrzanego, co by się wyróżniało.
Więc moje pytania:
- Czy powinienem martwić się dużą liczbą wywołań LogHelp_TerminateOnAssert?
- Czy aplikacja przecieka pamięć?
- Czy ma nadmierną liczbę wyjątków, które nie filtrują podczas uruchamiania aplikacji w programie Visual Studio?
Jedyny wpis z mojego kodu jest następujący, !get_FrameReceiveda stos dla tego wątku jest następujący:
Stos dla wątku z największą liczbą cykli wygląda następująco:
Odpowiedzi
Duże przesunięcia
clr.dll!LogHelp_TerminateOnAssert+0x6835
oznacza, że rzeczywiste wykonanie w tej metodzie jest oddalone o 0x6835 = 26661 bajtów od jej początku. Jest mało prawdopodobne, aby metoda była tak duża. (Jak wskazuje @blabb, jest to metoda 1-bajtowa).
Zwykle widzisz to, gdy nie ustawiłeś poprawnie symboli (jak w połączonym oryginalnym pytaniu), ale masz to naprawione.
Są szanse, że Microsoft wypuścił tylko symbole publiczne, clr.dlla nie prywatne. W takim przypadku zobaczysz tylko ostatnią znaną metodę publiczną.
Adres początkowy
Należy pamiętać, że nazwa kolumny to „Adres początkowy”. Process Explorer pokaże pierwszy wpis na stosie.
Tak więc wszystko się zaczyna. Wydaje się, że martwisz się, że na tym wszystko się kończy.
Uwaga: niektóre znane metody wewnętrzne, takie jak RtlUserThreadStarti, BaseThreadInitThunkzostaną pominięte podczas wyświetlania adresu początkowego. W przeciwnym razie prawdopodobnie wszystkie wyglądałyby tak samo.
To, co naprawdę robi wątek, znajduje się na szczycie listy, tj ZwRemoveIoCompletion. Wydaje się, że wykonuje jakąś operację we / wy.
Twoje pytania
Czy powinienem martwić się dużą liczbą wywołań LogHelp_TerminateOnAssert?
Nie. To tylko punkt wyjścia do czegoś dobrego. Do GetQueuedCompletionStatus()wygląda istnieje jakiś IO dzieje i .NET wykorzystuje IO Zakończenie Porty (IOCP) dla Ciebie.
Czy aplikacja przecieka pamięć?
Nie widać tego po spojrzeniu na stosy wywołań. Mówisz to, patrząc na wspomnienia w czasie.
Jeśli masz zbyt dużo operacji we / wy i sieć nie nadąża za tym, .NET może mieć coraz więcej elementów w kolejce, więc może to wyglądać na wyciek pamięci.
Czy ma nadmierną liczbę wyjątków, które nie filtrują podczas uruchamiania aplikacji w programie Visual Studio?
Nie można tego również powiedzieć ze stosu wywołań. Należy dołączyć debugger (np. WinDbg) i sprawdzić wyjątki (takie jak sxe clr), jeśli nie ufasz Visual Studio.
w kompilacji wydania wszystkie te potwierdzenia są kompilowane do prostego pliku ret, podobnego do
ifdef ( debug ) { function body here } elseif { ret } endif
więc symbole z tak dużym przesunięciem są fałszywe
więc może być konieczne załadowanie rzeczywistych symboli dla tego adresu dla rozsądnego stosu wywołań
widać, że rozmiar funkcji w clr 4.0.30319 clr.dll to tylko 1 bajt
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