为什么单个循环会导致内存泄漏?

4

我遇到了一个非常奇怪的行为。 使用这个虚拟代码:

 static void Main( string[] args )
    {
        int i = 0;

        while ( true )
        {
            i++;

            String giro = "iteration " + i;

            Console.WriteLine(giro);

            Thread.Sleep(40);
        }
    }

使用perfom时,私有字节正在增加。

img http://dl.dropbox.com/u/2478017/memory.gif

这怎么可能呢?

我以为GC会处理这些东西。

此外,如果我将其与每10次迭代强制进行GC收集的版本的内存行为进行比较,结果对我来说令人惊讶:

enter image description here

绿色的进程是没有GC.Collect()的,黑色的是另一个。你能帮我理解这个问题吗?谢谢!

1
从9.5到11 MB?你担心这个吗?它最终会被清理掉的,别担心。 - Botz3000
问题在于自2小时以来,内存的行为一直是这样的... - ff8mania
@ff8mania:这只是因为你的程序非常慢,大部分时间都在休眠。 - David Schwartz
你说得对。但是有人能解释一下为什么强制GC的版本总是平坦的吗? - ff8mania
它是扁平的,因为它总是被收集,就像你强制进行垃圾回收一样。 - Chris Walsh
7个回答

9

你正在创建一堆字符串。垃圾回收器还没有决定收集它们。最终,内存图形将会达到平稳状态。垃圾回收器运行良好 - 这里没有问题 :)


4
GC不会立即整理内存,这将非常低效。

1
使用 StringBuilder 而不是 String,看看是否可以解决您的问题。

1

没有泄漏。移除Thread.Sleep(40);并等待更长时间,垃圾回收器应该在一段时间后启动。


你能更好地解释一下你的回答吗? 为什么睡眠会影响GC? - ff8mania
1
@ff8mania: 我说移除 sleep 可以更快地创建 String 对象,以便更快地查看其对内存的影响。这样,您可以确定它是否会无限制地填充内存(真正的泄漏)还是只是 VM 或 GC 行为的副作用。我认为您的程序没有任何泄漏问题。 - mdakin
准确地说,它会达到平稳状态。这不是真正的泄漏。 - ff8mania

0

尝试更改这个:

String giro = "iteration " + i;
Console.WriteLine(giro);

Console.WriteLine("iteration " + i);

0

如果你需要垃圾回收器,你可以调用它:

                        GC.Collect();
                        GC.WaitForPendingFinalizers();

...不过它非常昂贵...


0

如果你定义了一个跳出循环的语句,它将解决你的问题。

 String giro;

  while ( true )
    {
        i++;

        giro = "iteration " + i;

        Console.WriteLine(giro);

        Thread.Sleep(40);
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接