我正在努力教育自己如何在C#这样的垃圾收集语言中发生泄漏或悬空引用。我在网上发现了一个人为的例子,我修改并观察(通过任务管理器),以便在每次击键时保持“漏水”。
来源:
using System;
using System.Collections.Generic;
namespace ConsoleApplication1
{
public class Something
{
int[] things;
public Something() {
things = new int[10000000];
Random rnd = new Random();
for (int i = 0; i < things.Length; ++i) {
things[i] = rnd.Next();
}
}
}
static public class SomethingFactory
{
public static Something CreateSomething() {
Something something = new Something();
return something;
}
}
class Program
{
static void Main(string[] args) {
while (true) {
Console.ReadKey();
Console.WriteLine("Creating...");
Something s = SomethingFactory.CreateSomething();
}
}
}
}
悬空参考为什么会出现?乍一看,似乎Something s
在while (true)
的范围内被实例化,并且在块结束之后,不应该存在对该项的其他引用。然而,随着每一次击键,我看到我的应用程序的内存使用量增加了约40mb,似乎永远不会下降。
答案 0 :(得分:1)
你没有做任何与众不同的事情。报告中报告的大量内存可以在样本中由GC回收。但是,请记住,当您在任务管理器中观察内存时,您正在查看进程内存。在托管应用程序中,CLR代表您的应用程序充当内存管理器。它在进程级别分配和释放内存。
工作方式是它分配内存块来存储托管堆上的对象。当对象数量下降时,这些卡盘最终会再次释放到OS。要记住的是CLR试图巧妙地做到这一点,因此每次托管堆更改时它都不会分配和释放。因此,通过查看进程级内存使用情况很难理解如何使用托管内存。
你看到的很可能就是内存被分配而不是被释放,因为CLR还没有任何理由来释放这些chucks。