C# GC 記憶體回收機制

來源:互聯網
上載者:User

標籤:

今天來談談C# 的GC ,也就是記憶體回收機制,非常的受教,總結如下

首先:談談託管,什麼叫託管,我的理解就是託付C# 運行環境幫我們去管理,在這個運行環境中可以協助我們開闢記憶體和釋放記憶體,開闢記憶體一般用new ,記憶體是隨機分配的,釋放主要靠的是GC 也就是記憶體回收機制。哪麼有兩個大問題 1.GC 可以回收任何對象嗎?2.GC 什麼時候來回收對象?回收那些對象?

對於第一個問題,GC 可以回收任何對象嗎?我是這樣理解的,首先要明白一點,C# 在強大也管不到Unmanaged 程式碼?哪麼什麼是Unmanaged 程式碼呢?比如stream (檔案),connection (資料庫連接),COM (組件)等等。。哪麼這些對象是需要進行串連的,比如說我們寫這樣一句話FileStream fs = new FileStream(“d://a.txt”,FileMode.Open); 實際上已經建立了和d://a.txt 的串連,如果重複兩次就會報錯。哪麼fs 這個對象叫做非託管對象,也就是說C#

不能自動去釋放和d://a.txt 的串連。哪麼對於非託管的代碼怎麼辦,一會我來說。

    對於第二個問題,GC 什麼時候來回收,回收什麼對象?我想後面的就不用我說了,當然是回收託管對象了。但是GC 什麼時候回收?是這樣的:GC 是隨機的,沒有人知道他什麼時候來,哪麼我寫了一個例子,證明這一點

private void button1_Click(object sender, EventArgs e)

{           

AA a = new  AA ();

AA b = new  AA ();

AA c = new  AA ();

AA d = new  AA ();

 

}

public class  AA{}

在講這個例子之前,要明白什麼被稱之為垃圾,垃圾就是一個記憶體地區,沒有被任何引用指向,或者不再會被用到。 哪麼在第一次點擊按鈕的時候會產生4 個對象,第二次點擊按鈕的時候也會產生4 個對象,但是第一次產生的4 個對象就已經是垃圾了,因為,第一次產生的4 個對象隨著 button1_Click 函數的結束而不會再被調用(或者說不能再被調用 ),哪麼這個時候GC 就會來回收嗎?不是的!我說了GC 是隨機的,哪麼你只管點你的,不一會GC 就會來回收的(這裡我們可以認為,記憶體中存在一定數量的垃圾之後,GC 會來 ),要證明GC 來過我們把AA 類改成

public class  AA

{

~AA()

{

        MessageBox .Show(" 解構函式被執行了" );

}

}

要明白,GC 清理垃圾,實際上是調用解構函式,但是這些代碼是Managed 程式碼(因為裡面沒有涉及到Steam ,Connection 等。。)所以在解構函式中,我們可以唯寫一個MsgBox 來證明剛的想法;這個時候,運行你的程式,一直點擊按鈕,不一會就會出現一大堆的“ 解構函式被執行了”…

 

    好了,然後讓我們看看能不能改變GC 這種為所欲為的天性,答案是可以的,我們可以通過調用GC.Collect(); 來強制GC 進行記憶體回收,哪麼button1_Click 修改如下

private void button1_Click(object sender, EventArgs e)

{           

AA a = new  AA ();

AA b = new  AA ();

AA c = new  AA ();

AA d = new  AA ();

GC .Collect();

}

哪麼在點擊第一次按鈕的時候,產生四個對象,然後強制記憶體回收,這個時候,會回收嗎?當然不會,因為,這四個對象還在執行中(方法還沒結束),當點第二次按鈕的時候,會出現四次" 解構函式被執行了" , 這是在釋放第一次點擊按鈕的四個對象,然後以後每次點擊都會出現四次" 解構函式被執行了" ,哪麼最後一次的對象什麼時候釋放的,在關閉程式的時候釋放(因為關閉程式要釋放所有的記憶體)。

 

好了,現在來談談Unmanaged 程式碼,剛才說過,Unmanaged 程式碼不能由記憶體回收釋放,我們把AA 類改成如下

public class  AA

{

     FileStream fs = new  FileStream ("D://a.txt" ,FileMode .Open);

     ~AA()

     {

            MessageBox .Show(" 解構函式被執行了" );

  }

}

private void button1_Click(object sender, EventArgs e)

{

            AA a = new  AA ();

}

如果是這樣一種情況,哪麼第二次點擊的時候就會報錯,原因是一個檔案只能建立一個串連。哪麼一定要釋放掉第一個資源,才可以進行第二次的串連。哪麼首先我們想到用 GC .Collect() ,來強制釋放閑置的資源,修改代碼如下:

private void button1_Click(object sender, EventArgs e)

{

            GC .Collect();

            AA a = new  AA ();

}

哪麼可以看到,第二次點按鈕的時候,確實出現了“解構函式被執行了“, 但是程式仍然錯了,原因前面我說過,因為Stream 不是Managed 程式碼,所以C# 不能幫我們回收,哪怎麼辦?

自己寫一個Dispose 方法;去釋放我們的記憶體。代碼如下:

public class  AA :IDisposable

    {

        FileStream fs = new  FileStream ("D://a.txt" ,FileMode .Open);

        ~AA()

        {

            MessageBox .Show(" 解構函式被執行了" );

 

        }

 

        #region IDisposable 成員

 

        public  void Dispose()

        {

            fs.Dispose();

            MessageBox .Show("dispose 執行了" );

        }

 

        #endregion

    }

好了,我們看到了,繼承 IDisposable 介面以後會有一個Dispose 方法(當然了,你不想繼承也可以,但是介面給我們提供一種規則,你不願意遵守這個規則,就永遠無法融入整個團隊,你的代碼只有你一個人能看懂),好了閑話不說,這樣一來我們的 button1_Click 改為private void button1_Click(object sender, EventArgs e)

{

            AA a = new  AA ();

a.Dispose();

}

我們每次點擊之後,都會發現執行了“ dispose 執行了”,在關閉程式的時候仍然執行了“解構函式被執行了”這意味了,GC 還是工作了,哪麼如果程式改為:

private void button1_Click(object sender, EventArgs e)

{

            AA a = new  AA ();

a.Dispose();

GC .Collect();

}

每次都既有“ dispose 執行了又有”“解構函式被執行了”,這意味著GC 又來搗亂了,哪麼像這樣包含Stream connection 的對象,就不用GC 來清理了,只需要我們加上最後一句話 GC.SuppressFinalize(this) 來告訴GC ,讓它不用再調用對象的解構函式中。 那麼改寫後的AA 的dispose 方法如下:

 

        public  void Dispose()

        {

            fs.Dispose();

            MessageBox .Show("dispose 執行了" );

GC.SuppressFinalize(this);

        }

C# GC 記憶體回收機制

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.