当前位置: 首页 > 知识库问答 >
问题:

第一次触发转储时出现问题OutOfMemoryException

漆雕正奇
2023-03-14

当第一次发生OutOfMemoryException时,我试图使用DebugDiag进行转储时遇到了一个问题。因此,我编写了一个应用程序,可以用来创建内存不足的情况,并遵循以下说明:

http://blogs.msdn.com/b/kaushal/archive/2012/05/09/using-debugdiag-to-capture-a-dump-on-first-chance-exception.aspx

但是我没有第一次转储,我只是得到了第二次转储。当我看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或其他地方获得了一个本机第一次机会异常,然后是OutOfMemoryException的CLR异常。我试图找出第一次出现的第二个异常是什么,我的代码如下所示:

private void OnGrowMemoryCommand(int growMemorySize)
{
    try
    {
        _heldMemoryChunks.Add(new byte[growMemorySize * 1024 * 1024]);
    }
    catch (Exception)
    {
        throw;
    }
    TotalMemorySize += growMemorySize;
}

这段代码是由WPF按钮上的命令触发的。因此,来自这段代码的任何异常都应该导致一个TargetInvocationExctive,我认为这是第一次机会异常中的第二个。然后最后是第二次机会异常,它属于TargetInvocationExctive类型。

所以我开始看第二次机会转储文件。我将其加载到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.

我可以看出,我的上述假设得到了以下事实的支持:第二次机会异常是TargetInvestationException异常,但为什么DebugDiag无法获取CLR异常类型?为了进行合理性检查,我尝试了一个实时调试会话。因此,我启动应用程序并附加,然后发出这些命令。

.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实例:

http://blogs.msdn.com/b/jjameson/archive/2011/01/11/issues-debugging-managed-code-in-windbg-with-sos-and-psscor2-e-g-quot-failed-to-request-threadstore-quot.aspx

所以我发出这些命令:

.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个答案

曾嘉瑞
2023-03-14

我在两台机器上遇到了同样的错误。都配备了。NET 4.5,所以我认为这是它不工作的原因。

原来这是DebugDiag脚本中的一个错误。它无法在其中一个脚本中检索CLR异常的名称。然而,这个问题是可以修复的,因为每个DebugDiag规则都创建了一个可以修改的vbs脚本。它使用相同的命令,你也可以在WinDbg中使用。以下是如何修复它:

>

  • 使用GUI创建DebugDiag规则,就像之前一样
  • 对于每个规则,都会生成一个vbs脚本文件。在C:\Program Files\DebugDiag\Scripts\CrashRule下的文本编辑器中打开它_

    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,我把它添加到SubDebugger_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 GUI中修改规则,所做的更改将被完全覆盖。

  •  类似资料:
    • 我有一个jdbc客户机与postgresql数据库通信。从JDBC中创建一条准备好的语句,用于在表中插入一些数据,但在创建查询时,客户机不知道要在语句中插入的所有字段,为了完成查询,我编写了一个触发器,在该表上插入之前触发,找到缺少的值,继续执行查询。这是jdbc代码: 这是触发代码: 当触发器触发时,我有一个错误: 这是什么意思?记录新的,正如你在jdbc代码中看到的那样。。。

    • 问题内容: 我已经阅读了有关创建触发器的Oracle文档,并且正在按照显示的方式进行操作,但是这是行不通的。我的目标是使用出现在TPM_TRAININGPLAN表中的最小STARTDATE更新TPM_PROJECT表。因此,每次有人更新TPM_TRAININGPLAN中的STARTDATE列时,我都想更新TPM_PROJECT表。这是我正在尝试的方法: 创建的触发器没有错误,但是我得到了警告: 当

    • 我面临QuartzScheduler触发器定义的问题。 2019年2月28日星期四16:27:30 IST:开始时间 0/20 0 0 ? * * * Cron表达式 2019年2月28日星期四16:29:30 IST结束时间 触发器schedulerAdderTrigger=触发器生成器。newTrigger()。withIdentity(触发键)。startAt(schedulerdata.g

    • 问题内容: 我想创建一个可以在表“合同”中修改或插入日期的触发器: “如果具有当前合同的客户签订了新合同,则前一个合同的结束日期将是新合同开始日期的前一天” 因此,我的 触发条件 是: 我试图插入这样的行: 该触发器可以很好地编译,但是他们在桌上没有做任何事情。 问题答案: 您想要这样的东西: 但是,它正在更新触发器正在监视的表,并且该触发器似乎将导致更新,该更新将再次调用该触发器并得到一个突变表

    • 但有没有更简单的解决办法呢?

    • 我想在点击某个div(“.checker”)后触发点击输入事件。换句话说,点击'.checker'将模拟点击复选框上的点击事件,远程检查它。 我写的代码可以工作,但click只有在第二次单击后才触发,第一次单击失败时才触发。这种情况甚至不会发生在'.checker'上,也会发生在checkbox上。 下面的所有HTML都包装在jquery折叠菜单中。单击“H3”后,“.sub-tree-wrap”