簡體   English   中英

.NET GC刪除正在使用的對象

[英].NET GC deleting object in use

我遇到了一個問題,在該問題中似乎GC線程正在喚醒並在使用對象時將其刪除。

當processfoo運行時,在返回之前,它會在單獨的線程中觸發fooCopy析構函數。 有人看到過這樣的問題嗎?如果是,您如何解決呢? 當然,這不可能真的發生,我必須做錯了什么。 誰能給我一些調試垃圾收集的提示/策略?

try
{
    CFoo fooCopy = new CFoo(someFoo);
    someBar.ProcessFoo(fooCopy);
}

CFoo具有IntPtr成員變量。 ProcessFoo將該成員變量從C ++ DLL傳遞到導入的函數,這可能需要花費幾秒鍾來運行。

在我的C ++ DLL中,我記錄了何時創建IntPtr以及何時刪除了IntPtr,並且可以看到在ProcessFoo運行時刪除IntPtr的單獨線程。

當然,這不可能真的發生,我必須做錯了什么。

是的,這絕對是有可能發生的(這就是為什么編寫終結器很難,並且您應該盡可能避免使用終結器,並且在強制編寫終結器時要非常小心)。 只要運行時證明沒有代碼會再次嘗試訪問該對象,就可以對其進行GC處理。 如果你調用一個實例方法(和任何時間調用之后從未訪問對象實例),那么物體的最近使用后立即可享有集合this從實例方法。

在范圍內(例如,方法的this變量)但在該范圍內不再使用的對象不會被GC視為根對象

至於如何解決它,如果您擁有一個即使不再在托管代碼中都無法訪問的變量,都希望將其視為“有效”的變量,請使用GC.KeepAlive 在這種情況下,將GC.KeepAlive(this)添加到ProcessFoo的末尾將確保所討論的對象保持活動狀態直到方法結束(或者,如果不是該方法的職責,請調用方調用GC.KeepAlive(someBar)就在ProcessFoo之后)。

有關主題的更多信息以及終結器的一些甚至更不尋常的屬性,請參見此博客文章

當您與C ++互操作時,這是很正常的,GC沒有希望發現IntPtr在其他任何地方都在使用。 這不是GC知道的參考類型,也不能探測本機代碼的堆棧框架。 抖動fooCopy對象引用標記為fooCopy使用基礎CALL,而不超出此范圍。 換句話說,它可以執行本機代碼時進行收集。 如果另一個線程觸發了GC,則為sayon​​ora。

您可以在這篇文章中找到有關局部變量生存期的詳細信息。

有幾種可能的解決方法,盡管無法從問題中猜出正確的方法。 除了SafeHandle類之外,還非常擅長確保完成終結處理,可以在[DllImport]聲明中使用HandleRef代替IntPtr。 或將GC.KeepAlive()附加到此代碼,以強制抖動延長fooCopy的壽命。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM