4 回答

TA貢獻1943條經驗 獲得超7個贊
事件處理程序是非常明顯的內存泄漏的常見來源。如果您從object2訂閱了object1上的事件,則執行object2.Dispose()并假裝該事件不存在(并從代碼中刪除所有引用),則object1的事件中存在一個隱式引用,這將阻止object2被垃圾收集。
MyType object2 = new MyType();
// ...
object1.SomeEvent += object2.myEventHandler;
// ...
// Should call this
// object1.SomeEvent -= object2.myEventHandler;
object2.Dispose();
這是泄漏的常見情況-忘記輕松取消訂閱事件。當然,如果收集了object1,則也將收集object2,但要到那時為止。

TA貢獻1803條經驗 獲得超6個贊
我認為C ++風格的內存泄漏是不可能的。垃圾收集器應解決這些問題。即使不再使用這些對象,也可以創建一個聚合對象引用的靜態對象。像這樣:
public static class SomethingFactory
{
private static List<Something> listOfSomethings = new List<Something>();
public static Something CreateSomething()
{
var something = new Something();
listOfSomethings.Add(something);
return something;
}
}
那顯然是一個愚蠢的例子,但這等同于托管運行時內存泄漏。

TA貢獻1856條經驗 獲得超17個贊
正如其他人指出的那樣,只要在內存管理器中沒有實際的錯誤,不使用非托管資源的類就不會泄漏內存。
在.NET中看到的不是內存泄漏,而是永不處置的對象。只要垃圾收集器可以在對象圖上找到對象,該對象就不會被處置。因此,如果任何活動對象在任何地方都具有對該對象的引用,則該對象不會被丟棄。
事件注冊是實現此目標的好方法。如果一個對象注冊了一個事件,則無論它注冊了什么對象,都具有對該事件的引用,并且即使您消除了對該對象的所有其他引用,直到該對象取消注冊(或與其注冊的對象變得不可訪問),它仍將保持活動狀態。
因此,您必須注意在不知情的情況下注冊靜態事件的對象。ToolStrip例如,的一個漂亮功能是,如果您更改顯示主題,它將自動在新主題中顯示。它通過注冊靜態SystemEvents.UserPreferenceChanged事件來實現此精美功能。更改Windows主題時,將引發該事件,并且ToolStrip正在監聽該事件的所有對象都將收到一個新主題的通知。
好的,假設您決定放棄ToolStrip表格上的:
private void DiscardMyToolstrip()
{
Controls.Remove("MyToolStrip");
}
您現在擁有一個ToolStrip永不消逝的世界。即使它不再存在于您的表單中,每次用戶更改主題時,Windows都會忠實地告知ToolStrip有關此主題的信息。每當垃圾收集器運行時,它都會認為“我不能扔掉該對象,UserPreferenceChanged事件正在使用它?!?/p>
那不是內存泄漏。但也可能如此。
這樣的事情使內存分析器變得無價。運行一個內存分析器,您會說:“很奇怪ToolStrip,即使我的表單上只有一個對象,堆上似乎有一萬個對象。這是怎么發生的?”
哦,如果您想知道為什么有些人認為屬性設置者是邪惡的:ToolStrip要從UserPreferenceChanged事件中取消注冊,請將其Visible屬性設置為false。
- 4 回答
- 0 關注
- 1119 瀏覽
添加回答
舉報