Проблемы при запуске дампа при исключении OutOfMemoryException
Я сталкиваюсь с проблемой при попытке использовать DebugDiag для создания дампа при возникновении исключительной ситуации OutOfMemoryException. Поэтому я написал приложение, которое я мог бы использовать для создания состояния нехватки памяти, и следуя приведенным ниже инструкциям:
Но я не получаю первый шанс, я просто получаю второй шанс. Когда я смотрю на файлы журнала от DebugDiag, я получаю это:
[6/16/2013 9:54:04 PM] First chance exception - 0xe06d7363 caused by thread with System ID: 4628
[6/16/2013 9:54:04 PM] First chance exception - 0xe0434352 caused by thread with System ID: 4628
[6/16/2013 9:54:05 PM] Unable to determine CLR exception type
ExceptionObjHexAddr = 0x00000000`00000000
bInnerException = False
DumpObject Output = Invalid parameter 0x00000000`00000000
ChildEBP RetAddr Args to Child
002bdee4 6a44c93f e0434352 00000001 00000005 KERNELBASE!RaiseException+0x58
002bdf88 6a573b17 00000000 20b578f4 002be04c clr!RaiseTheExceptionInternalOnly+0x276
002bdfb8 6a5e5589 20b54734 002be090 00000000 clr!UnwindAndContinueRethrowHelperAfterCatch+0x83
002be058 003c0a3a 00000000 00000000 0233d174 clr!JIT_NewArr1+0x1af
... removed some rows, lots of data ...
OS Thread Id: 0x1214 (0)
Child SP IP Call Site
002bdfd4 7554c41f [Frame: 002bdfd4]
002be060 003c0a3a
... removed some rows, lots of data ...
Error requesting GC Heap data
Unable to determine bounds of gc heap
Потом я получаю это:
[6/16/2013 9:54:05 PM] CLR Exception Type - ''
[6/16/2013 9:54:05 PM] First chance exception - 0xe0434352 caused by thread with System ID: 4628
[6/16/2013 9:54:05 PM] Unable to determine CLR exception type
Тогда наконец я получаю
[6/16/2013 9:54:05 PM] CLR Exception Type - ''
[6/16/2013 9:54:05 PM] C:\Windows\Microsoft.NET\Framework\v4.0.30319\diasymreader.dll loaded at 0x615c0000
[6/16/2013 9:54:13 PM] Second chance exception - 0xe0434352 caused by thread with System ID: 4628
Похоже, что он может получить адрес объекта исключения, он равен 0, поэтому, когда скрипт вызывает DumpObject, он не может найти информацию об исключении.
Способ, которым я читаю эти записи журнала, заключается в том, что я получаю собственное исключение первого шанса от malloc или чего-то еще, а затем следует исключение CLR для OutOfMemoryException. Я пытаюсь выяснить, что является вторым из исключений первого шанса, мой код выглядит так:
private void OnGrowMemoryCommand(int growMemorySize)
{
try
{
_heldMemoryChunks.Add(new byte[growMemorySize * 1024 * 1024]);
}
catch (Exception)
{
throw;
}
TotalMemorySize += growMemorySize;
}
Этот код запускается из команды на кнопку WPF. Из-за этого любые исключения, происходящие из этого кода, должны приводить к исключению TargetInvocationException, которое, я считаю, является вторым из исключений первого шанса. Затем, наконец, из блока throw возникает исключение второго шанса, которое имеет тип TargetInvocationException.
Поэтому я начинаю смотреть на файл дампа второго шанса. Я загружаю его в windbg, затем выдаю следующие команды:
.symfix C:\symcache
.loadby sos clr
.reload
!pe
Exception object: 023caf9c
Exception type: System.Reflection.TargetInvocationException
Message: Exception has been thrown by the target of an invocation.
InnerException: System.OutOfMemoryException, Use !PrintException 023c9928 to see more.
Я вижу, что мои предположения, изложенные выше, подтверждаются тем фактом, что исключение второго шанса является исключением TargetInvocationException, но почему DebugDiag не может получить типы исключений CLR? Для проверки работоспособности я пробую сеанс live-отладки. Поэтому я запускаю приложение и присоединяюсь, а затем выдаю эти команды.
.symfix C:\symcache
.loadby sos clr
.reload
!threads
Failed to request ThreadStore
!dumpheap
The garbage collector data structures are not in a valid state for traversal.
It is either in the "plan phase," where objects are being moved around, or
we are at the initialization or shutdown of the gc heap. Commands related to
displaying, finding or traversing objects as well as gc heap segments may not
work properly. !dumpheap and !verifyheap may incorrectly complain of heap
consistency errors.
Error requesting GC Heap data
Unable to build snapshot of the garbage collector state
Это полностью шланг. Итак, я начинаю исследовать эту проблему.
Этот URL предполагает, что это может быть несколько экземпляров CLR:
Поэтому я выдаю эти команды:
.cordll
CLR DLL status: Loaded DLL C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscordacwks.dll
Это странно для меня, я думал, что с 4.0 на том mscorwks был исключен в пользу clr. Это mscordacwks 4.5?
Я выдал эту команду:
lmvm mscordacwks
Но clr загружается:
lmvm clr
start end module name
6a350000 6a9e2000 clr (pdb symbols) C:\symcache\clr.pdb\97FD69E1786F42F9A541C81D81AC96852\clr.pdb
Loaded symbol image file: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
Image path: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
Image name: clr.dll
Timestamp: Fri Mar 29 00:13:44 2013 (51553118)
CheckSum: 0069496E
ImageSize: 00692000
File version: 4.0.30319.18047
Product version: 4.0.30319.18047
File flags: 8 (Mask 3F) Private
File OS: 4 Unknown Win32
File type: 2.0 Dll
File date: 00000000.00000000
Translations: 0409.04b0
CompanyName: Microsoft Corporation
ProductName: Microsoft® .NET Framework
InternalName: clr.dll
OriginalFilename: clr.dll
ProductVersion: 4.0.30319.18047
FileVersion: 4.0.30319.18047 built by: FX45RTMGDR
PrivateBuild: DDBLD316
FileDescription: Microsoft .NET Runtime Common Language Runtime - WorkStation
LegalCopyright: © Microsoft Corporation. All rights reserved.
Comments: Flavor=Retail
Поэтому я не думаю, что у меня загружено несколько CLR.
Таким образом, я предполагаю, что то же самое, что вызывает мои проблемы с отладкой в реальном времени, приводит к тому, что я не могу запустить проблему первого шанса. Есть идеи?
1 ответ
Я сталкивался с той же ошибкой на двух машинах. Оба были оснащены.NET 4.5, поэтому я думаю, что по этой причине он не работал.
Это оказалось ошибкой в сценариях DebugDiag. Он не может получить имя исключения CLR в одном из своих сценариев. Однако эта проблема исправима, так как каждое правило DebugDiag создает сценарий VBS, который можно изменить. Он использует те же самые команды, которые вы также можете использовать в WinDbg. Вот как это исправить:
- Создайте правило DebugDiag с помощью графического интерфейса, как вы уже сделали.
- Для каждого правила создается файл сценария VBS. Откройте его в текстовом редакторе под
C:\Program Files\DebugDiag\Scripts\CrashRule_<rulename>.vbs
- Найти функцию
GetCLRExceptionType
Измените его следующим образом:
Function GetCLRExceptionType(ByVal ExceptionObjHexAddr, ByVal bInnerException) Dim Output, Lines, i If Debugger.IsClrExtensionMissing Then WriteToLog "Unable to determine CLR exception type - extension dll could not be loaded." Else ' Output = Debugger.Execute("!DumpObj " & ExceptionObjHexAddr) ' Does not work in .NET 4.5 Output = Debugger.Execute("!pe") ' FIX .NET45 Lines = Split(Output, Chr(10)) For i = 0 To UBound(Lines) If bInnerException Then If InStr(Lines(i), "_innerException") <> 0 Then Tokens = Split(Lines(i), " ") For j = 0 To UBound(Tokens) If Len(Tokens(j)) = 8 Then GetCLRExceptionType = GetCLRExceptionType(Tokens(j), False) Exit For End If Next End If ElseIf Len(Lines(i)) >= 7 Then If InStr(Lines(i), "Exception type:") = 1 Then ' FIX .NET45 GetCLRExceptionType = Trim(Mid(Lines(i), 16)) ' FIX .NET45 Exit For End If End If Next If GetCLRExceptionType = "" Then If g_ClrExceptionTypeFailureLogCount < MAX_CLR_EXCEPTION_TYPE_FAILURE_LOG_ENTRIES Then g_ClrExceptionTypeFailureLogCount = g_ClrExceptionTypeFailureLogCount + 1 WriteToLog "Unable to determine CLR exception type" & vbcrlf & _ "ExceptionObjHexAddr = " & ExceptionObjHexAddr & vbcrlf & _ "bInnerException = " & bInnerException & vbcrlf & _ "DumpObject Output = " & Output & vbcrlf & _ Debugger.Execute("kb100") & vbcrlf & _ Debugger.Execute("!clrstack") & vbcrlf & _ Debugger.Execute("!dso") End If End If End If End Function
По умолчанию, !DumpObj
используется для выгрузки содержимого объекта исключения. Однако что-то изменилось в.NET 4.5 и, очевидно, тип исключения больше не может быть извлечен. Вместо этого поместите !pe
Здесь команда и проанализировать тип исключения из его результата.
Чтобы сделать !pe
работа, нужно сделать .loadby sos clr
, Я добавил это в Sub Debugger_OnLoadModule
:
Sub Debugger_OnLoadModule(ByVal NewModule)
WriteToLog NewModule.ImageName & " loaded at " & Debugger.GetAs32BitHexString(NewModule.Base)
Select Case UCase(NewModule.ModuleName)
Case "MSCORWKS", "MSCORSVR", "CLR", "CORECLR"
UpdateDeferredManagedBreakpoints
End Select
Debugger.Execute(".loadby sos clr")
End Sub
После внесения изменений необходимо либо перезапустить процессы, либо деактивировать / повторно активировать правило, чтобы применить его.
Также: имейте в виду, что если вы измените свое правило в графическом интерфейсе DebugDiag, ваши изменения будут полностью перезаписаны.