【发布时间】:2013-09-12 01:39:37
【问题描述】:
我一直在开发一个数据导出程序,该程序从数据库中提取大量记录。其中一个步骤涉及将 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 会被处理掉,但事实并非如此。
【问题讨论】:
-
我怀疑是因为 clr 没有感觉到任何内存压力,所以还没有运行 GC,但是 windows 用完了句柄
-
代码完整吗?您是否将 rtfBox 附加到其他控件?
-
Windows 句柄是非托管资源(与内存不同),因此 GC 不会“感受到”来自它的压力。在这种情况下,程序员有责任调用 dispose()。