日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當(dāng)前位置:首頁 > 科技  > 軟件

.Net析構(gòu)函數(shù)再論(源碼剖析)

來源: 責(zé)編: 時(shí)間:2023-10-10 18:31:51 273觀看
導(dǎo)讀1.前言本篇繼續(xù)看下析構(gòu)函數(shù)的一些引申知識(shí)。2.概述析構(gòu)函數(shù)目前發(fā)現(xiàn)的總共有三個(gè)標(biāo)記,這里分別一一介紹下。先上一段代碼:internal class Program : IDisposable{ static void Main(string[] args){ Stre

1.前言

本篇繼續(xù)看下析構(gòu)函數(shù)的一些引申知識(shí)。x4128資訊網(wǎng)——每日最新資訊28at.com

2.概述

析構(gòu)函數(shù)目前發(fā)現(xiàn)的總共有三個(gè)標(biāo)記,這里分別一一介紹下。先上一段代碼:x4128資訊網(wǎng)——每日最新資訊28at.com

internal class Program :  IDisposable{     static void Main(string[] args){         StreamReader? streamReader = null;         streamReader = new StreamReader("Test_.dll");         streamReader?.Dispose();         Console.ReadLine();     }     ~Program(){         Console.WriteLine("調(diào)用了析構(gòu)函數(shù)");     }     public void Dispose(){         this.Dispose();         GC.SuppressFinalize(this);     } }

這里的析構(gòu)函數(shù)跟Dispose一起混用, ~Program()析構(gòu)函數(shù)會(huì)通過Roslyn生成x4128資訊網(wǎng)——每日最新資訊28at.com

.method family hidebysig virtual instance void         Finalize() cil managed{  .override [System.Runtime]System.Object::Finalize  // 代碼大小       24 (0x18)  .maxstack  1  IL_0000:  nop  .try  {    IL_0001:  nop    IL_0002:  ldstr      bytearray (03 8C 28 75 86 4E 90 67 84 67 FD 51 70 65 )       // ..(u.N.g.g.Qpe    IL_0007:  call       void [System.Console]System.Console::WriteLine(string)    IL_000c:  nop    IL_000d:  leave.s    IL_0017  }  // end .try  finally{    IL_000f:  ldarg.0    IL_0010:  call       instance void [System.Runtime]System.Object::Finalize()    IL_0015:  nop    IL_0016:  endfinally  }  // end handler  IL_0017:  ret} // end of method Program::Finalize

這里同時(shí)需要注意 streamReader?.Dispose();這句話,streamreader實(shí)際上繼承的是textreaderx4128資訊網(wǎng)——每日最新資訊28at.com

public class StreamReader : TextReader{}

所以它調(diào)用Dispose的代碼是TextReader里面的Dispose:x4128資訊網(wǎng)——每日最新資訊28at.com

public void Dispose() {     Dispose(true);     GC.SuppressFinalize(this); }

也就是關(guān)閉了streamReader流。然后base.Dispose.這個(gè)base.Dispose實(shí)際上就是它的父類TextReader里面的x4128資訊網(wǎng)——每日最新資訊28at.com

public void Dispose(){   this._streamReader.close();}

Dispose里面的下面一句代碼x4128資訊網(wǎng)——每日最新資訊28at.com

GC.SuppressFinalize(this);

它是重點(diǎn)。x4128資訊網(wǎng)——每日最新資訊28at.com

GC.SuppressFinalize

1.判斷當(dāng)前類是否有析構(gòu)函數(shù)

如果類里面有析構(gòu)函數(shù),比如例子里的Program,則會(huì)設(shè)置MethodTable的成員m_dwFlagsx4128資訊網(wǎng)——每日最新資訊28at.com

m_dwFlags |= enum_flag_HasFinalizer(0x00100000);

它的設(shè)置邏輯是如果存在析構(gòu)函數(shù),并且當(dāng)前方法不是接口,不是虛方法,方法的索引小于當(dāng)前類的索引數(shù),當(dāng)前的方法不是Object.Finlize()。那么說明當(dāng)前這個(gè)類有析構(gòu)函數(shù),所以需要在當(dāng)前類的MethodTable上進(jìn)行操作,也即上面的m_dwFlags位設(shè)置。x4128資訊網(wǎng)——每日最新資訊28at.com

邏輯代碼如下:x4128資訊網(wǎng)——每日最新資訊28at.com

//存在析構(gòu)函數(shù),并且當(dāng)前方法不是接口,不是虛方法if (g_pObjectFinalizerMD && !IsInterface() && !IsValueClass()){    WORD slot = g_pObjectFinalizerMD->GetSlot();    //方法的索引小于當(dāng)前類宗的索引數(shù),當(dāng)前的方法不是Object.Finlize()    if (slot < bmtVT->cVirtualSlots && (*bmtVT)[slot].Impl().GetMethodDesc() != g_pObjectFinalizerMD)    {        GetHalfBakedMethodTable()->SetHasFinalizer(); //這個(gè)地方就是設(shè)置m_dwFlags        //此處省略一萬行    }}

2.調(diào)用GC.SuppressFinalize

設(shè)置當(dāng)前類的對(duì)象頭

headerobj|BIT_SBLK_FINALIZER_RUN當(dāng)我們調(diào)用GC.SuppressFinalize的時(shí)候,它會(huì)進(jìn)行判斷m_dwFlags或上的enum_flag_HasFinalizer位是否為1,如果位0直接返回,如果為1,則設(shè)置對(duì)象頭。它的判斷邏輯如下x4128資訊網(wǎng)——每日最新資訊28at.com

if (!obj->GetMethodTable ()->HasFinalizer())//HasFinalizer函數(shù)判斷m_dwFlags的enum_flag_HasFinalizer位return;GCHeapUtilities::GetGCHeap()->SetFinalizationRun(obj);//這里設(shè)置當(dāng)前類的對(duì)象頭headerobj|BIT_SBLK_FINALIZER_RUNBIT_SBLK_FINALIZER_RUN定義如下:#define BIT_SBLK_FINALIZER_RUN   0x40000000

3.對(duì)象進(jìn)行分配空間的時(shí)候

設(shè)置flags |= GC_ALLOC_FINALIZE一個(gè)對(duì)象需要進(jìn)行空間的分配,當(dāng)進(jìn)行空間分配的時(shí)候,它會(huì)判斷當(dāng)前函數(shù)是否包含了析構(gòu)函數(shù)。如果包含了,則設(shè)置flags標(biāo)志最后一位位1.然后在對(duì)象分配的時(shí)候,把它放入到析構(gòu)隊(duì)列里面去。x4128資訊網(wǎng)——每日最新資訊28at.com

if (pMT->HasFinalizer())//判斷當(dāng)前類是否包含析構(gòu)函數(shù)    flags |= GC_ALLOC_FINALIZE;//如果包含則設(shè)置flags最后一位為1GC_ALLOC_FINALIZE定義如下:enum GC_ALLOC_FLAGS{    GC_ALLOC_NO_FLAGS           = 0,    GC_ALLOC_FINALIZE           = 1,    GC_ALLOC_CONTAINS_REF       = 2,    GC_ALLOC_ALIGN8_BIAS        = 4,    GC_ALLOC_ALIGN8             = 8,    GC_ALLOC_ZEROING_OPTIONAL   = 16,    GC_ALLOC_LARGE_OBJECT_HEAP  = 32,    GC_ALLOC_PINNED_OBJECT_HEAP = 64,    GC_ALLOC_USER_OLD_HEAP      = GC_ALLOC_LARGE_OBJECT_HEAP | GC_ALLOC_PINNED_OBJECT_HEAP,};

當(dāng)進(jìn)行對(duì)象分配的時(shí)候,它會(huì)判斷falgs最后一位是否為1,如果為1,則把對(duì)象放入到析構(gòu)隊(duì)列,不為1,則不放入。x4128資訊網(wǎng)——每日最新資訊28at.com

CHECK_ALLOC_AND_POSSIBLY_REGISTER_FOR_FINALIZATION(newAlloc, size, flags & GC_ALLOC_FINALIZE); //flags & GC_ALLOC_FINALIZE判斷falgs最后一位是否為1.#define CHECK_ALLOC_AND_POSSIBLY_REGISTER_FOR_FINALIZATION(_object, _size, _register) do {    //這里的register就是flags & GC_ALLOC_FINALIZE的值,下面的邏輯如果對(duì)象為空直接返回,如果不為空則判斷flags & GC_ALLOC_FINALIZE是否等于1,如果為零直接返回,如果為1,則調(diào)用REGISTER_FOR_FINALIZATION,把對(duì)象放入析構(gòu)隊(duì)列    if ((_object) == NULL || ((_register) && !REGISTER_FOR_FINALIZATION(_object, _size)))     {        STRESS_LOG_OOM_STACK(_size);        return NULL;    }

以上是析構(gòu)函數(shù),GC.SuppressFinalize,Dispose的最底層邏輯。當(dāng)然這里還有很多技術(shù)問題需要解決。后面再看。x4128資訊網(wǎng)——每日最新資訊28at.com

標(biāo)記的作用

GC.SuppressFinalize問題來了,它的這些標(biāo)記有什么用呢?這是一個(gè)非常繞的問題,分析下。首先的enum_flag_HasFinalizer標(biāo)記表示當(dāng)前類包含了析構(gòu)函數(shù),GC_ALLOC_FINALIZE標(biāo)記表示當(dāng)前的類對(duì)象需要填充到析構(gòu)隊(duì)列里面去。

而BIT_SBLK_FINALIZER_RUN標(biāo)記是最為重要的,它如果被標(biāo)記了則表示從析構(gòu)隊(duì)列里面溢出,不需要運(yùn)行這個(gè)當(dāng)前類的析構(gòu)函數(shù)。x4128資訊網(wǎng)——每日最新資訊28at.com

在GC的標(biāo)記階段標(biāo)記對(duì)象是否存活完成之后,它需要對(duì)對(duì)象的析構(gòu)隊(duì)列進(jìn)行掃描。如果析構(gòu)隊(duì)列(SegQueue)里的對(duì)象被標(biāo)記存活,且它的對(duì)象頭有x4128資訊網(wǎng)——每日最新資訊28at.com

BIT_SBLK_FINALIZER_RUN標(biāo)志,則表示此對(duì)象的析構(gòu)隊(duì)列里的對(duì)象可以移出了,也就是不運(yùn)行此對(duì)象的析構(gòu)函數(shù)。x4128資訊網(wǎng)——每日最新資訊28at.com

//這里的ScanForFinalization是在GCScanRoot之運(yùn)行的,還有一個(gè)從析構(gòu)函數(shù)里面取出//對(duì)象運(yùn)行析構(gòu)函數(shù)則是GCHeap::GetNextFinalizableObjectCFinalize::ScanForFinalization (promote_func* pfn, int gen, BOOL mark_only_p,                                gc_heap* hp){     //判斷對(duì)象頭是否標(biāo)記了BIT_SBLK_FINALIZER_RUN  if ((obj->GetHeader()->GetBits()) & BIT_SBLK_FINALIZER_RUN)                    {                        //如果標(biāo)記了,則把這個(gè)對(duì)象移除到FreeList,也即是空閑的析構(gòu)列表,不然存在于析構(gòu)列表中                        MoveItem (i, Seg, FreeList);                        //然后清除掉此對(duì)象頭BIT_SBLK_FINALIZER_RUN標(biāo)志                        obj->GetHeader()->ClrBit (BIT_SBLK_FINALIZER_RUN);                    }}
再論CLR析構(gòu)函數(shù) 6 析構(gòu)函數(shù)的幾個(gè)特性CLR析構(gòu)列表是如何添加析構(gòu)函數(shù)類的

本文鏈接:http://www.www897cc.com/showinfo-26-12734-0.html.Net析構(gòu)函數(shù)再論(源碼剖析)

聲明:本網(wǎng)頁內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com

上一篇: Docker容器化構(gòu)建可擴(kuò)展的分布式緩存系統(tǒng):Memcached和Redis

下一篇: 喝了100杯醬香拿鐵,我開竅了

標(biāo)簽:
  • 熱門焦點(diǎn)
Top 主站蜘蛛池模板: 民权县| 上犹县| 出国| 宜宾市| 田林县| 股票| 镇巴县| 观塘区| 武威市| 南乐县| 丰镇市| 瑞丽市| 农安县| 富裕县| 张北县| 伽师县| 杭锦后旗| 扶风县| 东阳市| 金华市| 鞍山市| 昌平区| 大庆市| 广州市| 射阳县| 冀州市| 洞口县| 建始县| 高雄市| 陆良县| 丰原市| 隆林| 积石山| 安西县| 驻马店市| 卢氏县| 涪陵区| 东城区| 鹤岗市| 济宁市| 闸北区|