内存分配问题?

时间:2010-01-21 11:45:32

标签: c# .net oop memory-management

public static void Main()
        {
            Test t1 = new Test();
}

何时t1(引用变量)将在编译时或运行时获得内存 我认为应该是运行时间。但是当我在Main方法中设置断点并监视t1时,它为空。所以这意味着t1在记忆中。

如果我错了,请纠正我。

编辑:我听说静态成员变量是在编译时分配的。

8 个答案:

答案 0 :(得分:5)

内存仅在运行时分配(在编译时您的应用程序未运行)。

在运行时,您的t1变量在赋值发生后只会有一个值(即不是null),因此它取决于您放置断点的位置。如果你将断点放在Main方法的右大括号上,并在看到它时检查观察窗口,你会看到我的意思。

即。如果将断点放在赋值行Test1 t1 = new Test1();上,那么该行尚未执行,因此未进行赋值。

答案 1 :(得分:3)

引用t1在Main方法的堆栈帧上分配 - 您分配给它的值(即'new Test()'部分)在运行时分配在堆上 - 这就是t1变量之前存在的原因该行已执行且为空。

答案 2 :(得分:2)

Test t1;

这部分只为引用分配了足够的空间(在很多情况下可能只有4个字节,但我认为它实际上取决于.NET框架实现),并且在编译时确定并且在调用Main时分配(我认为)

t1 = new Test();

该行在运行时将分配足够的空间来存储Test对象的数据,然后分配现有的引用变量t1以引用新分配的内存。所以现在你有了t1的空间加上新的Test()的空间都被分配了。

编辑:要响应您的编辑,静态成员变量是不同的,并且您的本地变量的行为与它们不同。但是,我不相信在编译时分配静态成员变量。我认为在加载包含它们的类型时会分配它们(这似乎是在调用任何引用该类型的函数时)。

class Test2
{
   public static Test f1 = new Test();
}

只要调用包含对Test2类型的任何引用的函数,此代码就会创建一个新的Test实例。

答案 3 :(得分:2)

在'Main'的开头,尚未分配实例的堆内存(并且直到new Test()才会分配)。它将保持分配,直到它被垃圾收集。

将引用堆内存的局部变量Test t1(基于堆栈)确实存在(并且在'Main'正在执行的整个时间内存在)。

这两个都是运行时分配,但在内存所在位置和持续时间方面有所不同。

静态字段在类型加载时分配(并在当时和类型首次使用之间的某个时间初始化)。

通过'compile-time',我不确定你是否指的是JIT编译 - 但无论哪种方式,内存都是与编译分开分配的。

答案 4 :(得分:1)

不,这意味着尚未分配t1。一旦你调用new Test() t1,将分配内存来存储Test对象的大小,并为其分配一个内存地址。

是内存仅在运行时分配。

答案 5 :(得分:1)

你应该能够自己解决这个问题。试想一下:

  • 当您分配内存时,您可以“使用”内存。
  • 不运行的程序,不使用内存。
  • 运行的程序,使用内存。
  • 在运行时,表示程序正在运行。
  • 在运行时使用,分配内存。

分配内存编译时间,没有任何意义......

答案 6 :(得分:1)

在阅读了上述答案之后,让我试着用更好的方式来表达答案。

让我们以这种方式放置代码:

Main()
{
  Test t1;
  t1 = new Test();
}

现在,让我们开始吧:

  1. 将调试点放在{,测试t1,t1 =新测试()和}
  2. 运行程序
  3. 让声明{执行 - 没有任何名称为t1 - 为什么??

    编程正在运行。 汇编很久以前就完成了。 仍然 - t1永远不会分配内存。为什么呢?

  4. 转到下一个调试点,让Test t1语句执行。

    现在检查 - 您会发现本地变量/内存列表中存在t1。

    为什么呢?该声明已处理完毕,并且是RUN / RAN / Executed。所以,它被分配了内存。

    现在 - 分配了什么内存?它只是 Reference / Pointer / Object所需的内存。 它显然应该具有null值。那么 - 你认为需要多少记忆?

  5. 现在让下一个语句执行。

    这一次,null的值被其他东西取代 - 这确实占用了可变的内存量,具体取决于它的作用。

  6. 处理下一个陈述:

    现在发生的事情是您的对象不再存在/或不再被引用。

    是否仍然为仍然存在的对象/分配的内存分配了内存 new Test()为测试t1分配的内存? - 是的!

    此内存仍然存在,但幸运的是 - 垃圾收集器存在并清除垃圾。

    从效率的角度来看,最好设置Test t1=null,以便在主函数有很多其他语句可以使用的情况下,它可以解除分配为新测试分配的内存()通过信号通知垃圾收集器不再需要这块数据。

    Main(或变量的范围)结束时,垃圾收集器检查指针以引用某个值 - 如果它没有(因为它为null),它就会继续也取消分配引用/对象内存。

  7. @Static东西:我试图自己找出静态类/变量和方法。

    @people: 如果我在某个地方错了,请纠正我。

答案 7 :(得分:0)

在调试模式下运行应用程序,F5主要是visual studio中的键盘快捷键。在这个声明中加上一个断点。使用F10进入下一个语句。当调试器步骤下一个语句时,您将看到正在创建的对象。