国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

淺談CLR的內存分配和回收機制

2019-11-17 04:46:13
字體:
來源:轉載
供稿:網友

  相對于C++程序員來說,C#程序員是非常幸運的,至少我們不需要為內存泄漏(Memory Leak)而頭疼,不需要負責內存的分配和回收。但這不意味著我們只需要知道new的語法就可以了,作為一個嚴厲的C#程序員,我們應該對此有所了解,有助于我們編寫性能更好的代碼。

  一、CLR的內存分配機制

  .NET Framework 的垃圾回收器治理應用程序的內存分配和釋放。每次使用 new 運算符創建對象時,運行庫都從托管堆為該對象分配內存。只要托管堆中有地址空間可用,運行庫就會繼續為新對象分配空間。

...
object obj = new object();
...
  但是,內存不是無限大的。

public void FillMemory()
{
 ArrayList memory = new ArrayList();
 // 輸出填充前所占內存大小
 Console.WriteLine("used memory:" + GC.GetTotalMemory(false));

 for (int i = 0; i < 100000; i++)
 {
  memory.Add(new string("foo"));
 }
 // 輸出填充后所占的內存大小
 Console.WriteLine("used memory:" + GC.GetTotalMemory(false));
}
  最終,垃圾回收器必須執行回收以釋放一些內存。垃圾回收器優化引擎根據正在進行的分配情況確定執行回收的最佳時間。當垃圾回收器執行回收時,它檢查托管堆中不再被應用程序使用的對象并執行必要的操作往返收它們占用的內存。

  二、CLR的內存回收機制

  一般我們在程序中創建的對象大部分都是托管對象,可依靠GC自動進行內存的回收,但是對于封裝了非托管資源的對象,就需要我們顯式重載object.Finalize()接口來實現非托管資源的釋放。

using System;
using System.IO;

public class Foo
{
 PRivate FileStream _stream;

 public Foo()
 {
  _stream = new FileStream(@"c:/foo.txt", FileMode.Open);
 }

 // some other Operation here...
 
 ~Foo()
 {
  // release the unmanaged resource
  _stream.Close();
 }
}
  * 析構函數會在編譯時會被翻譯為protected void Finalize(),這是C#的析構函數的語法

  GC在回收對象之前會調用Finalize()來實現非托管資源的釋放,不過按照MSDN的說法,Finalize()會導致性能的降低。

  “垃圾回收器使用名為“終止隊列”的內部結構跟蹤具有 Finalize 方法的對象。每次您的應用程序創建具有 Finalize 方法的對象時,垃圾回收器都在終止隊列中放置一個指向該對象的項。托管堆中所有需要在垃圾回收器回收其內存之前調用它們的終止代碼的對象都在終止隊列中含有項。

  實現 Finalize 方法或析構函數對性能可能會有負面影響,因此應避免不必要地使用它們。用 Finalize 方法回收對象使用的內存需要至少兩次垃圾回收。當垃圾回收器執行回收時,它只回收沒有終結器的不可訪問對象的內存。這時,它不能回收具有終結器的不可訪問對象。它改為將這些對象的項從終止隊列中移除并將它們放置在標為預備終止的對象列表中。該列表中的項指向托管堆中預備被調用其終止代碼的對象。垃圾回收器為此列表中的對象調用 Finalize 方法,然后,將這些項從列表中移除。后來的垃圾回收將確定終止的對象確實是垃圾,因為標為預備終止對象的列表中的項不再指向它們。在后來的垃圾回收中,實際上回收了對象的內存。” --[MSDN]

  更加建議實現Sytem.IDisposable.Dispose()接口,用來實現對非托管資源的釋放,這也是.Net Framework中常見的設計模式。那該怎么實現Dispose呢?

  1、首先,Dispose接口應該釋放自身對象所占用的資源,還應該調用基類的Dispose方法,釋放基類部分所占用的資源。

public void Dispose()
{
 // do something to release my unmanaged resource
 ReleaseMyResource();

 base.Dispose();
}
  2、前面說過Finalize()會導致性能問題,那么在執行Dispose以后就應該告訴GC不用在調用Finalize()了

public void Dispose()
{
 // do something to release my unmanaged resource
 ReleaseMyResource();
 base.Dispose();

 // tell gc not to call Finalize()
 GC.SuppressFinalize(this);
}
  當然我們完全可以定義一個MySpace.IClosable.Close(),通過實現這個接口來進行非托管資源的釋放,不過這實在沒有必要。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 渝北区| 朝阳市| 元朗区| 津市市| 宁海县| 安龙县| 游戏| 山东| 康定县| 嵩明县| 广灵县| 盐边县| 拜泉县| 永定县| 麟游县| 额济纳旗| 太仆寺旗| 虎林市| 南昌县| 柳林县| 家居| 沙田区| 乾安县| 苏尼特右旗| 双峰县| 汉川市| 海城市| 凤庆县| 娱乐| 密云县| 普兰店市| 张家港市| 道真| 深泽县| 昭苏县| 澜沧| 澄城县| 邯郸市| 邯郸市| 阿拉善左旗| 柞水县|