使用Windbg调试.NET OutOfMemory异常

Debug .NET OutOfMemoryException with windbg(使用Windbg调试.NET OutOfMemory异常)

本文介绍了使用Windbg调试.NET OutOfMemory异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要帮助来调试.Net DLL中将RTF文本转换为原始文本或html格式的OutOfMemoyException。

这里是转换的代码,(http://matthewmanela.com/blog/converting-rtf-to-html/)

public string ConvertRtfToHtml(string rtfText)
{
    if (rtfText.Equals("")) return "";
    try
    {
        var thread = new Thread(ConvertRtfInSTAThread);
        var threadData = new ConvertRtfThreadData { RtfText = rtfText };
        thread.SetApartmentState(ApartmentState.STA);
        thread.Start(threadData);
        thread.Join();

        return threadData.HtmlText;
    }
    catch (Exception e)
    {
        GestionErreurConv.EnregistrerErreur("Convert", "ConvertRtfToHtml", e.Message);
        return rtfText;
    }
}

private void ConvertRtfInSTAThread(object rtf)
{
    try
    {
        var threadData = (ConvertRtfThreadData)rtf;
        var converter = new RtfToHtmlConverter();
        threadData.HtmlText = converter.ConvertRtfToHtml(threadData.RtfText);
    }
    catch (Exception e)
    {
        GestionErreurConv.EnregistrerErreur("Convert", "ConvertRtfToHtml", e.Message);
    }
}

public class RtfToHtmlConverter
{
    private const string FlowDocumentFormat = "<FlowDocument>{0}</FlowDocument>";

    public string ConvertRtfToHtml(string rtfText)
    {
        var xamlText = string.Format(FlowDocumentFormat, ConvertRtfToXaml(rtfText));
        var converter = new HtmlFromXamlConverter();
        return converter.ConvertXamlToHtml(xamlText, false);
    }

    private string ConvertRtfToXaml(string rtfText)
    {
        string returnString;

        try
        {
            var richTextBox = new RichTextBox
            {
                UndoLimit = 0,
                IsUndoEnabled = false
            };

            var textRange = new TextRange(richTextBox.Document.ContentStart, richTextBox.Document.ContentEnd);

            //Create a MemoryStream of the Rtf content
            using (var rtfMemoryStream = new MemoryStream())
            {
                using (var rtfStreamWriter = new StreamWriter(rtfMemoryStream))
                {
                    rtfStreamWriter.Write(rtfText);
                    rtfStreamWriter.Flush();
                    rtfMemoryStream.Seek(0, SeekOrigin.Begin);

                    //Load the MemoryStream into TextRange ranging from start to end of RichTextBox.
                    textRange.Load(rtfMemoryStream, DataFormats.Rtf);
                }
            }

            using (var rtfMemoryStream = new MemoryStream())
            {
                textRange = new TextRange(richTextBox.Document.ContentStart, richTextBox.Document.ContentEnd);
                textRange.Save(rtfMemoryStream, DataFormats.Xaml);
                rtfMemoryStream.Seek(0, SeekOrigin.Begin);
                using (var rtfStreamReader = new StreamReader(rtfMemoryStream)) { 
                    returnString = rtfStreamReader.ReadToEnd();
                }
            }

            // Libération mémoire
            GC.Collect();
            GC.WaitForPendingFinalizers();

            return returnString;
        }
        catch (Exception)
        {
            // Libération mémoire
            GC.Collect();
            GC.WaitForPendingFinalizers();
            return rtfText;
        }
    }
}

/// <summary>
/// HtmlToXamlConverter is a static class that takes an HTML string
/// and converts it into XAML
/// </summary>
public class HtmlFromXamlConverter
{
    #region Public Methods

    /// <summary>
    /// Main entry point for Xaml-to-Html converter.
    /// Converts a xaml string into html string.
    /// </summary>
    /// <param name="xamlString">
    /// Xaml strinng to convert.
    /// </param>
    /// <returns>
    /// Html string produced from a source xaml.
    /// </returns>
    public string ConvertXamlToHtml(string xamlString, bool asFullDocument)
    {
        var htmlStringBuilder = new StringBuilder(100);

        using (var xamlReader = new XmlTextReader(new StringReader(xamlString)))
        using (var htmlWriter = new XmlTextWriter(new StringWriter(htmlStringBuilder)))
        {
            if (!WriteFlowDocument(xamlReader, htmlWriter, asFullDocument))
            {
                return "";
            }

            return htmlStringBuilder.ToString();
        }
    }

    #endregion Public Methods

    // ---------------------------------------------------------------------
    //
    // Private Methods
    //
    // ---------------------------------------------------------------------

    #region Private Methods
    /// <summary>
    /// Processes a root level element of XAML (normally it's FlowDocument element).
    /// </summary>
    /// <param name="xamlReader">
    /// XmlTextReader for a source xaml.
    /// </param>
    /// <param name="htmlWriter">
    /// XmlTextWriter producing resulting html
    /// </param>
    private bool WriteFlowDocument(XmlTextReader xamlReader, XmlTextWriter htmlWriter, bool asFullDocument)
    {
        if (!ReadNextToken(xamlReader))
        {
            // Xaml content is empty - nothing to convert
            return false;
        }

        if (xamlReader.NodeType != XmlNodeType.Element || xamlReader.Name != "FlowDocument")
        {
            // Root FlowDocument elemet is missing
            return false;
        }

        // Create a buffer StringBuilder for collecting css properties for inline STYLE attributes
        // on every element level (it will be re-initialized on every level).
        var inlineStyle = new StringBuilder();

        if (asFullDocument)
        {
            htmlWriter.WriteStartElement("HTML");
            htmlWriter.WriteStartElement("BODY");
        }

        WriteFormattingProperties(xamlReader, htmlWriter, inlineStyle);

        WriteElementContent(xamlReader, htmlWriter, inlineStyle);

        if (asFullDocument)
        {
            htmlWriter.WriteEndElement();
            htmlWriter.WriteEndElement();
        }
        return true;
    }

    /// <summary>
    /// Reads attributes of the current xaml element and converts
    /// them into appropriate html attributes or css styles.
    /// </summary>
    /// <param name="xamlReader">
    /// XmlTextReader which is expected to be at XmlNodeType.Element
    /// (opening element tag) position.
    /// The reader will remain at the same level after function complete.
    /// </param>
    /// <param name="htmlWriter">
    /// XmlTextWriter for output html, which is expected to be in
    /// after WriteStartElement state.
    /// </param>
    /// <param name="inlineStyle">
    /// String builder for collecting css properties for inline STYLE attribute.
    /// </param>
    private void WriteFormattingProperties(XmlTextReader xamlReader, XmlTextWriter htmlWriter, StringBuilder inlineStyle)
    {
        // Clear string builder for the inline style
        inlineStyle.Remove(0, inlineStyle.Length);

        if (!xamlReader.HasAttributes)
        {
            return;
        }

        bool borderSet = false;

        while (xamlReader.MoveToNextAttribute())
        {
            string css = null;

            switch (xamlReader.Name)
            {
                // Character fomatting properties
                // ------------------------------
                case "Background":
                    css = "background-color:" + ParseXamlColor(xamlReader.Value) + ";";
                    break;
                case "FontFamily":
                    css = "font-family:" + xamlReader.Value + ";";
                    break;
                case "FontStyle":
                    css = "font-style:" + xamlReader.Value.ToLower() + ";";
                    break;
                case "FontWeight":
                    css = "font-weight:" + xamlReader.Value.ToLower() + ";";
                    break;
                case "FontStretch":
                    break;
                case "FontSize":
                    css = "font-size:" + xamlReader.Value + "px;";
                    break;
                case "Foreground":
                    css = "color:" + ParseXamlColor(xamlReader.Value) + ";";
                    break;
                case "TextDecorations":
                    if (xamlReader.Value.ToLower() == "strikethrough")
                        css = "text-decoration:line-through;";
                    else
                        css = "text-decoration:underline;";
                    break;
                case "TextEffects":
                    break;
                case "Emphasis":
                    break;
                case "StandardLigatures":
                    break;
                case "Variants":
                    break;
                case "Capitals":
                    break;
                case "Fraction":
                    break;

                // Paragraph formatting properties
                // -------------------------------
                case "Padding":
                    css = "padding:" + ParseXamlThickness(xamlReader.Value) + ";";
                    break;
                case "Margin":
                    css = "margin:" + ParseXamlThickness(xamlReader.Value) + ";";
                    break;
                case "BorderThickness":
                    css = "border-width:" + ParseXamlThickness(xamlReader.Value) + ";";
                    borderSet = true;
                    break;
                case "BorderBrush":
                    css = "border-color:" + ParseXamlColor(xamlReader.Value) + ";";
                    borderSet = true;
                    break;
                case "LineHeight":
                    break;
                case "TextIndent":
                    css = "text-indent:" + xamlReader.Value + ";";
                    break;
                case "TextAlignment":
                    css = "text-align:" + xamlReader.Value + ";";
                    break;
                case "IsKeptTogether":
                    break;
                case "IsKeptWithNext":
                    break;
                case "ColumnBreakBefore":
                    break;
                case "PageBreakBefore":
                    break;
                case "FlowDirection":
                    break;

                // Table attributes
                // ----------------
                case "Width":
                    css = "width:" + xamlReader.Value + ";";
                    break;
                case "ColumnSpan":
                    htmlWriter.WriteAttributeString("COLSPAN", xamlReader.Value);
                    break;
                case "RowSpan":
                    htmlWriter.WriteAttributeString("ROWSPAN", xamlReader.Value);
                    break;

                // Hyperlink Attributes
                case "NavigateUri":
                    htmlWriter.WriteAttributeString("HREF", xamlReader.Value);
                    break;

                case "TargetName":
                    htmlWriter.WriteAttributeString("TARGET", xamlReader.Value);
                    break;
            }

            if (css != null)
            {
                inlineStyle.Append(css);
            }
        }

        if (borderSet)
        {
            inlineStyle.Append("border-style:solid;mso-element:para-border-div;");
        }

        // Return the xamlReader back to element level
        xamlReader.MoveToElement();
    }

    private string ParseXamlColor(string color)
    {
        if (color.StartsWith("#"))
        {
            // Remove transparancy value
            color = "#" + color.Substring(3);
        }
        return color;
    }

    private string ParseXamlThickness(string thickness)
    {
        string[] values = thickness.Split(',');

        for (int i = 0; i < values.Length; i++)
        {
            if (double.TryParse(values[i], out double value))
            {
                values[i] = Math.Ceiling(value).ToString();
            }
            else
            {
                values[i] = "1";
            }
        }

        switch (values.Length)
        {
            case 1:
                return thickness;
            case 2:
                return values[1] + " " + values[0];
            case 4:
                return values[1] + " " + values[2] + " " + values[3] + " " + values[0];
            default:
                return values[0];
        }
    }

    /// <summary>
    /// Reads a content of current xaml element, converts it
    /// </summary>
    /// <param name="xamlReader">
    /// XmlTextReader which is expected to be at XmlNodeType.Element
    /// (opening element tag) position.
    /// </param>
    /// <param name="htmlWriter">
    /// May be null, in which case we are skipping the xaml element;
    /// witout producing any output to html.
    /// </param>
    /// <param name="inlineStyle">
    /// StringBuilder used for collecting css properties for inline STYLE attribute.
    /// </param>
    private void WriteElementContent(XmlTextReader xamlReader, XmlTextWriter htmlWriter, StringBuilder inlineStyle)
    {
        bool elementContentStarted = false;

        if (xamlReader.IsEmptyElement)
        {
            if (htmlWriter != null && !elementContentStarted && inlineStyle.Length > 0)
            {
                // Output STYLE attribute and clear inlineStyle buffer.
                htmlWriter.WriteAttributeString("STYLE", inlineStyle.ToString());
                inlineStyle.Remove(0, inlineStyle.Length);
            }
            elementContentStarted = true;
        }
        else
        {
            while (ReadNextToken(xamlReader) && xamlReader.NodeType != XmlNodeType.EndElement)
            {
                switch (xamlReader.NodeType)
                {
                    case XmlNodeType.Element:
                        if (xamlReader.Name.Contains("."))
                        {
                            AddComplexProperty(xamlReader, inlineStyle);
                        }
                        else
                        {
                            if (htmlWriter != null && !elementContentStarted && inlineStyle.Length > 0)
                            {
                                // Output STYLE attribute and clear inlineStyle buffer.
                                htmlWriter.WriteAttributeString("STYLE", inlineStyle.ToString());
                                inlineStyle.Remove(0, inlineStyle.Length);
                            }
                            elementContentStarted = true;
                            WriteElement(xamlReader, htmlWriter, inlineStyle);
                        }
                        Debug.Assert(xamlReader.NodeType == XmlNodeType.EndElement || xamlReader.NodeType == XmlNodeType.Element && xamlReader.IsEmptyElement);
                        break;
                    case XmlNodeType.Comment:
                        if (htmlWriter != null)
                        {
                            if (!elementContentStarted && inlineStyle.Length > 0)
                            {
                                htmlWriter.WriteAttributeString("STYLE", inlineStyle.ToString());
                            }
                            htmlWriter.WriteComment(xamlReader.Value);
                        }
                        elementContentStarted = true;
                        break;
                    case XmlNodeType.CDATA:
                    case XmlNodeType.Text:
                    case XmlNodeType.SignificantWhitespace:
                        if (htmlWriter != null)
                        {
                            if (!elementContentStarted && inlineStyle.Length > 0)
                            {
                                htmlWriter.WriteAttributeString("STYLE", inlineStyle.ToString());
                            }
                            htmlWriter.WriteString(xamlReader.Value);
                        }
                        elementContentStarted = true;
                        break;
                }
            }
        }
    }

    /// <summary>
    /// Conberts an element notation of complex property into
    /// </summary>
    /// <param name="xamlReader">
    /// On entry this XmlTextReader must be on Element start tag;
    /// on exit - on EndElement tag.
    /// </param>
    /// <param name="inlineStyle">
    /// StringBuilder containing a value for STYLE attribute.
    /// </param>
    private void AddComplexProperty(XmlTextReader xamlReader, StringBuilder inlineStyle)
    {
        if (inlineStyle != null && xamlReader.Name.EndsWith(".TextDecorations"))
        {
            inlineStyle.Append("text-decoration:underline;");
        }

        // Skip the element representing the complex property
        WriteElementContent(xamlReader, /*htmlWriter:*/null, /*inlineStyle:*/null);
    }

    /// <summary>
    /// Converts a xaml element into an appropriate html element.
    /// </summary>
    /// <param name="xamlReader">
    /// On entry this XmlTextReader must be on Element start tag;
    /// on exit - on EndElement tag.
    /// </param>
    /// <param name="htmlWriter">
    /// May be null, in which case we are skipping xaml content
    /// without producing any html output
    /// </param>
    /// <param name="inlineStyle">
    /// StringBuilder used for collecting css properties for inline STYLE attributes on every level.
    /// </param>
    private void WriteElement(XmlTextReader xamlReader, XmlTextWriter htmlWriter, StringBuilder inlineStyle)
    {
        if (htmlWriter == null)
        {
            // Skipping mode; recurse into the xaml element without any output
            WriteElementContent(xamlReader, /*htmlWriter:*/null, null);
        }
        else
        {
            string htmlElementName;
            switch (xamlReader.Name)
            {
                case "Run" :
                case "Span":
                case "InlineUIContainer":
                    htmlElementName = "SPAN";
                    break;
                case "Bold":
                    htmlElementName = "B";
                    break;
                case "Italic" :
                    htmlElementName = "I";
                    break;
                case "Paragraph" :
                    htmlElementName = "P";
                    break;
                case "BlockUIContainer":
                case "Section":
                    htmlElementName = "DIV";
                    break;
                case "Table":
                    htmlElementName = "TABLE";
                    break;
                case "TableColumn":
                    htmlElementName = "COL";
                    break;
                case "TableRowGroup" :
                    htmlElementName = "TBODY";
                    break;
                case "TableRow" :
                    htmlElementName = "TR";
                    break;
                case "TableCell" :
                    htmlElementName = "TD";
                    break;
                case "List" :
                    string marker = xamlReader.GetAttribute("MarkerStyle");
                    if (marker == null || marker == "None" || marker == "Disc" || marker == "Circle" || marker == "Square" || marker == "Box")
                    {
                        htmlElementName = "UL";
                    }
                    else
                    {
                        htmlElementName = "OL";
                    }
                    break;
                case "ListItem" :
                    htmlElementName = "LI";
                    break;
                case "Hyperlink":
                    htmlElementName = "A";
                    break;
                default :
                    htmlElementName = null; // Ignore the element
                    break;
            }

            if (htmlWriter != null && htmlElementName != null)
            {
                htmlWriter.WriteStartElement(htmlElementName);

                WriteFormattingProperties(xamlReader, htmlWriter, inlineStyle);

                WriteElementContent(xamlReader, htmlWriter, inlineStyle);

                htmlWriter.WriteEndElement();
            }
            else
            {
                // Skip this unrecognized xaml element
                WriteElementContent(xamlReader, /*htmlWriter:*/null, null);
            }
        }
    }

    // Reader advance helpers
    // ----------------------

    /// <summary>
    /// Reads several items from xamlReader skipping all non-significant stuff.
    /// </summary>
    /// <param name="xamlReader">
    /// XmlTextReader from tokens are being read.
    /// </param>
    /// <returns>
    /// True if new token is available; false if end of stream reached.
    /// </returns>
    private bool ReadNextToken(XmlReader xamlReader)
    {
        while (xamlReader.Read())
        {
            switch (xamlReader.NodeType)
            {
                case XmlNodeType.Element: 
                case XmlNodeType.EndElement:
                case XmlNodeType.None:
                case XmlNodeType.CDATA:
                case XmlNodeType.Text:
                case XmlNodeType.SignificantWhitespace:
                    return true;

                case XmlNodeType.Whitespace:
                    if (xamlReader.XmlSpace == XmlSpace.Preserve)
                    {
                        return true;
                    }
                    // ignore insignificant whitespace
                    break;

                case XmlNodeType.EndEntity:
                case XmlNodeType.EntityReference:
                    //  Implement entity reading
                    //xamlReader.ResolveEntity();
                    //xamlReader.Read();
                    //ReadChildNodes( parent, parentBaseUri, xamlReader, positionInfo);
                    break; // for now we ignore entities as insignificant stuff

                case XmlNodeType.Comment:
                    return true;
                case XmlNodeType.ProcessingInstruction:
                case XmlNodeType.DocumentType:
                case XmlNodeType.XmlDeclaration:
                default:
                    // Ignorable stuff
                    break;
            }
        }
        return false;
    }

    #endregion Private Methods
}

}

此DLL由Windows服务使用,ConvertRtfToHtml方法被多次调用。

这是Windbg信息:

    0:016> !sos.clrstack
OS Thread Id: 0x220c (16)
Child SP       IP Call Site
127beb0c 755bc232 [GCFrame: 127beb0c] 
127bebcc 755bc232 [HelperMethodFrame_2OBJ: 127bebcc] System.Environment.GetResourceFromDefault(System.String)
127bec50 10fa493c System.Environment.GetResourceString(System.String, System.Object[])
127bec60 10fa48af System.Exception.get_Message()
127bec70 069077d9 *** WARNING: Unable to verify checksum for Convertisseur.dll
SQWebContributeur.Convertisseur.Convert.ConvertRtfInSTAThread(System.Object) [D:SOLU-QIQProjets SVNDLL MaisonConvertisseurConvertisseurConvert.cs @ 268]
127bed94 069052d4 System.Threading.ThreadHelper.ThreadStart_Context(System.Object)
127beda0 063e2c17 System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
127bee10 063e2177 System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
127bee24 06905162 System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
127bee3c 069050e3 System.Threading.ThreadHelper.ThreadStart(System.Object)
127bef80 730eebf6 [GCFrame: 127bef80] 
127bf164 730eebf6 [DebuggerU2MCatchHandlerFrame: 127bf164] 


0:016> !pe -nested
Exception object: 019bbfc0
Exception type:   System.Runtime.InteropServices.COMException
    Message:          Espace insuffisant pour traiter cette commande. (Exception de HRESULT : 0x80070008)
InnerException:   <none>
StackTrace (generated):
    SP       IP       Function
    00000000 00000001 UNKNOWN!System.Environment.GetResourceFromDefault(System.String)+0x2
    127BEC50 10FA493C UNKNOWN!System.Environment.GetResourceString(System.String, System.Object[])+0xc
    127BEC60 10FA48AF UNKNOWN!System.Exception.get_Message()+0x4f
    127BEC70 069077D9 Convertisseur_ae70000!SQWebContributeur.Convertisseur.Convert.ConvertRtfInSTAThread(System.Object)+0xe9
    127BED94 069052D4 UNKNOWN!System.Threading.ThreadHelper.ThreadStart_Context(System.Object)+0x9c
    127BEDA0 063E2C17 UNKNOWN!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)+0x107
    127BEE10 063E2177 UNKNOWN!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)+0x17
    127BEE24 06905162 UNKNOWN!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)+0x3a
    127BEE3C 069050E3 UNKNOWN!System.Threading.ThreadHelper.ThreadStart(System.Object)+0x4b

StackTraceString: <none>
HResult: 80070008

Nested exception -------------------------------------------------------------
Exception object: 019b9dc4
Exception type:   System.OutOfMemoryException
Message:          <none>
InnerException:   <none>
StackTrace (generated):
    SP       IP       Function
    00000000 00000001 UNKNOWN!System.GC._WaitForPendingFinalizers()+0x2
    127BEB68 10FA11DF UNKNOWN!System.GC.WaitForPendingFinalizers()+0x4f
    127BEB98 0C55631D Convertisseur_ae70000!SQWebContributeur.ClassesHelp.RtfToHtmlConverter.ConvertRtfToXaml(System.String)+0x385
    127BED00 069078C9 Convertisseur_ae70000!SQWebContributeur.ClassesHelp.RtfToHtmlConverter.ConvertRtfToHtml(System.String)+0x51
    127BED38 0690779C Convertisseur_ae70000!SQWebContributeur.Convertisseur.Convert.ConvertRtfInSTAThread(System.Object)+0xac

StackTraceString: <none>
HResult: 8007000e

!eeheap-gc命令显示垃圾收集器使用了4个Mo:

0:016> !eeheap -gc
Number of GC Heaps: 1
generation 0 starts at 0x019b9db8
generation 1 starts at 0x019b9cec
generation 2 starts at 0x01861000
ephemeral segment allocation context: none
 segment     begin  allocated      size
01860000  01861000  01bec808  0x38b808(3717128)
Large object heap starts at 0x02861000
 segment     begin  allocated      size
02860000  02861000  028ba260  0x59260(365152)
Total Size:              Size: 0x3e4a68 (4082280) bytes.
------------------------------
GC Heap Size:    Size: 0x3e4a68 (4082280) bytes.

!Dumpheap-stat命令显示只有2个Mo是空闲的:

00e6a430      865      2382762      Free

以下是PerfMon数据:

我不知道该怎么做来解决这个例外。我尝试添加EgCollect()来强制GC,但没有任何效果。

该VM具有8个Go物理内存,而在另一个具有4个Go的VM上,不会发生异常。我不知道如何解决此例外。

感谢您的帮助

推荐答案

首先,您很好地提取了所有内部异常,以便确定此崩溃是由OOM异常引起的。并不是所有的开发人员都具备这种技能。

!eeheap -gc命令显示垃圾收集器使用了4个Mo

这是正确的-这是一个强有力的迹象,表明垃圾收集本身并不会真正起到帮助作用。即使它可以释放这4 MB空间,您也几乎什么也得不到。

(但稍后将详细说明)

!dumpheap -stat命令显示只有2个Mo是空闲的

虽然此语句没有错误,但它也不完整。

A)有2 MB空闲空间,但这2 MB被拆分到865个不同的区域。因此可能仍不可能分配单个2 MB数据块

B)从.NET的角度来看,这2 MB是免费的。如果.NET没有足够的可用内存,它将向操作系统请求更多内存。然后,该请求可能成功,也可能失败,具体取决于操作系统可提供的内存量。

记住这些知识后,您需要询问

为什么操作系统无法为.NET提供更多内存?

原因可能是:因为它已经释放了所有内存。在32位进程中,这是2 GB、3 GB或4 GB,具体取决于配置和设置(主要是大地址感知)。这不是很多,尤其是,它不能作为连续的块使用。在许多情况下,您只有700 MB。

操作系统会在哪里提供内存?以COM对象为例(因为我们有一个COM异常,但这可能会产生误导)。而且这些COM对象似乎是本机的(否则它们将分配托管内存)。查看.NET内存将无济于事。

但是,有一个例外:如果您的.NET代码是COM对象未被释放的原因,那么您的.NET代码就是本机内存泄漏的间接原因。因此,您应该寻找的是RCW对象的数量。如果你有很多这样的东西,你需要想办法摆脱它们。

如果不是这个原因,可能是您的RTF太大,无法放入最大的可用内存区域。

我曾经编造了一个graph for tackling down OOM exceptions,告诉您从哪里开始。

通过!address -summary,您可以了解操作系统的观点。

您可能有一个很小的<unknown>值,因为.NET使用量很小。

如果Heap具有较大的值,则内存将通过Windows堆管理器(例如C++)耗尽,并且存在本机泄漏(可能是由于未释放COM对象所致)。

您还可以查看"按大小计算的最大区域"一节,在那里您可以找到Free的值。这是一个人通过一个请求可以获得的最大值。可能它不足以匹配您的数据。

这篇关于使用Windbg调试.NET OutOfMemory异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本文标题为:使用Windbg调试.NET OutOfMemory异常

基础教程推荐