.NET垃圾收集:调试与发行conundrum
>>本文探讨了一个常见的.NET垃圾收集怪癖:为什么在调试构建中可能不会最终确定对象,而是在发行版中。 考虑此代码:
<code class="language-csharp">public class Class1 { public static int c; ~Class1() { c++; } } public class Class2 { public static void Main() { { var c1 = new Class1(); //c1 = null; // Uncommenting doesn't significantly change release behavior } GC.Collect(); GC.WaitForPendingFinalizers(); Console.WriteLine(Class1.c); // Prints 0 in debug, 1 in release Console.Read(); } }</code>神秘感:
不在范围内,但其最终器并未在调试模式下运行。c1
调试器的影响
关键在于调试器与.NET JIT编译器的交互。 在调试期间,JIT修改了跟踪本地可变寿命的内部表。 这种修改扩大了本地变量的寿命,即使它们在逻辑上超出范围之后,您也可以检查它们。 这可以防止调试期间的过早垃圾收集。
释放构建行为
>在发行版构建中运行代码(无JIT优化)揭示了预期的行为。是最终确定的,c1
增量,并且控制台输出“ 1”。Class1.c
>没有调试器的垃圾收集
>没有调试器,垃圾收集器可有效收回内存。 即使包含参考的方法仍在运行,如果该方法不再直接引用该方法,则该对象也有资格收集。这样可以防止内存泄漏。
line c1 = null;
c1
没有显着改变发布构建结果。 JIT优化器可能会删除此线,因为它在功能上是多余的。
null
调试和释放构建之间垃圾收集行为的差异源于调试器对JIT编译器的影响。 始终在发行版中测试与垃圾收集相关的代码,以确保在生产环境中进行准确的结果。 了解这种区别对于避免出乎意料的行为和潜在的记忆问题至关重要。
以上是为什么垃圾收集不在调试构建中最终确定我的对象,而是在发行版本中最终确定了我的对象呢?的详细内容。更多信息请关注PHP中文网其他相关文章!