.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中文網其他相關文章!