【发布时间】:2014-10-13 16:53:18
【问题描述】:
我正在尝试让自己了解在 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,而且似乎从未下降。
【问题讨论】:
-
您是在运行调试代码还是附加了调试器?尝试在 Release 模式下不使用调试器运行它。
-
在调试模式下,变量的范围是到函数的末尾,因此直到 Main() 结束时才被收集
-
垃圾收集器会在需要清理内存时收集你的垃圾。也许是因为你有足够的内存,它没有被收集。您可以通过将
Console.ReadKey();替换为if (Console.ReadLine == 'g') GC.Collect();来或多或少地“模拟”垃圾收集器。在运行您的应用程序期间,输入“g”以启动垃圾收集器。但是,您永远不应该在您的代码中这样做。垃圾收集器经过优化,可以在必要时运行。手动操作是不好的做法。仅供演示使用。 -
我根本看不到任何“泄漏”。删除 Console.ReadKey() 调用,以便您可以看到它的长期行为。
-
@mikez 我正在运行
Debug构建。调试器与否,它仍然执行相同的操作,但是Release构建按预期执行。内存第一次跳跃约 40mb 并停留在那里。Debug有何不同?
标签: c# memory-management garbage-collection