gpt4 book ai didi

c# - 为什么我的 C# 方法存在用户对象的内存泄漏?

转载 作者:太空宇宙 更新时间:2023-11-03 17:14:58 24 4
gpt4 key购买 nike

我一直在研究从数据库中提取大量记录的数据导出程序。其中一个步骤涉及将 RTF 文本字符串转换为纯文本,这最终导致用户对象在运行时发生内存泄漏。任务管理器将显示的列之一是“USER objects”——当它达到 ~10,000 时,程序将用完分配空间,程序将出现“错误创建窗口句柄”错误

发生这种情况是因为我没有在方法结束时处理我的对象。

我的问题是,为什么 C#/.net 没有为我处理它?

这是一个可以重现泄漏的快速代码示例。将代码放入 Winforms 应用程序并按下按钮以使其循环遍历内存浪费。

private void wasteMemory()
{
System.Windows.Forms.RichTextBox rtfBox = new System.Windows.Forms.RichTextBox();

//RTF text that reads "Hello World"
rtfBox.Rtf = "{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang1033{\\fonttbl{\\f0\\fnil\\fcharset0 Arial;}} {\\colortbl ;\\red0\\green0\\blue0;} \\viewkind4\\uc1\\pard\\cf1\\fs29 Hello World} ";

//If line below is commented out, User Objects grow out of control.
//rtfBox.Dispose();
}

private void button1_Click(object sender, EventArgs e)
{
for (int i = 1; i < 100000; i++)
{
wasteMemory();
}
}

据我了解,方法的范围内创建的任何对象都会在方法完成时被处理掉。我预计 rtfBox 会被处理掉,但它没有。

最佳答案

到目前为止,这里的每个答案都不完整。是的,确实必须清理非托管资源,但实现 IDisposable 的类已经这样做了。这不是重点。

在正确实现 IDisposable 的类中,如果未显式或隐式处置对象,则将在垃圾回收的终结器阶段处置该对象。但是,当对象超出范围时,此过程不会立即发生。 gc 运行可能需要几分钟甚至几小时。

这里的问题是,如果您自己不调用 Dispose()(或通过将其包装在 using 语句中隐式调用 Dispose()),那么(如果类正确实现了)该对象将不会被释放,直到垃圾收集器运行,这可能需要相当长的时间。

这意味着在垃圾收集器开始处理未引用的对象之前,您可能会用完非托管资源。而这正是您遇到的问题。

自己调用 Dispose() 可确保非托管对象在您处理完它们后立即被清理,而不是在 GC 处理它时。

把它想象成一个图书馆。有人借了一本书,书架上有 5 本。当其他人借阅该图书馆时,有些人会归还它们……但它们不会立即被放在书架上,它们会坐在归还箱中,直到有人抽出时间检查它们并重新上架。

调用 Dispose 就像将书交给图书管理员,让他们立即登记,然后将其放回书架,以便下一个人可以拿到。

关于c# - 为什么我的 C# 方法存在用户对象的内存泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18747309/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com