AVt天堂网 手机版,亚洲va久久久噜噜噜久久4399,天天综合亚洲色在线精品,亚洲一级Av无码毛片久久精品

當前位置:首頁 > 科技  > 軟件

.Net析構函數再論(源碼剖析)

來源: 責編: 時間:2023-10-10 18:31:51 219觀看
導讀1.前言本篇繼續看下析構函數的一些引申知識。2.概述析構函數目前發現的總共有三個標記,這里分別一一介紹下。先上一段代碼:internal class Program : IDisposable{ static void Main(string[] args){ Stre

1.前言

本篇繼續看下析構函數的一些引申知識。TXH28資訊網——每日最新資訊28at.com

2.概述

析構函數目前發現的總共有三個標記,這里分別一一介紹下。先上一段代碼:TXH28資訊網——每日最新資訊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("調用了析構函數");     }     public void Dispose(){         this.Dispose();         GC.SuppressFinalize(this);     } }

這里的析構函數跟Dispose一起混用, ~Program()析構函數會通過Roslyn生成TXH28資訊網——每日最新資訊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

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

public class StreamReader : TextReader{}

所以它調用Dispose的代碼是TextReader里面的Dispose:TXH28資訊網——每日最新資訊28at.com

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

也就是關閉了streamReader流。然后base.Dispose.這個base.Dispose實際上就是它的父類TextReader里面的TXH28資訊網——每日最新資訊28at.com

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

Dispose里面的下面一句代碼TXH28資訊網——每日最新資訊28at.com

GC.SuppressFinalize(this);

它是重點。TXH28資訊網——每日最新資訊28at.com

GC.SuppressFinalize

1.判斷當前類是否有析構函數

如果類里面有析構函數,比如例子里的Program,則會設置MethodTable的成員m_dwFlagsTXH28資訊網——每日最新資訊28at.com

m_dwFlags |= enum_flag_HasFinalizer(0x00100000);

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

邏輯代碼如下:TXH28資訊網——每日最新資訊28at.com

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

2.調用GC.SuppressFinalize

設置當前類的對象頭

headerobj|BIT_SBLK_FINALIZER_RUN當我們調用GC.SuppressFinalize的時候,它會進行判斷m_dwFlags或上的enum_flag_HasFinalizer位是否為1,如果位0直接返回,如果為1,則設置對象頭。它的判斷邏輯如下TXH28資訊網——每日最新資訊28at.com

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

3.對象進行分配空間的時候

設置flags |= GC_ALLOC_FINALIZE一個對象需要進行空間的分配,當進行空間分配的時候,它會判斷當前函數是否包含了析構函數。如果包含了,則設置flags標志最后一位位1.然后在對象分配的時候,把它放入到析構隊列里面去。TXH28資訊網——每日最新資訊28at.com

if (pMT->HasFinalizer())//判斷當前類是否包含析構函數    flags |= GC_ALLOC_FINALIZE;//如果包含則設置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,};

當進行對象分配的時候,它會判斷falgs最后一位是否為1,如果為1,則把對象放入到析構隊列,不為1,則不放入。TXH28資訊網——每日最新資訊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的值,下面的邏輯如果對象為空直接返回,如果不為空則判斷flags & GC_ALLOC_FINALIZE是否等于1,如果為零直接返回,如果為1,則調用REGISTER_FOR_FINALIZATION,把對象放入析構隊列    if ((_object) == NULL || ((_register) && !REGISTER_FOR_FINALIZATION(_object, _size)))     {        STRESS_LOG_OOM_STACK(_size);        return NULL;    }

以上是析構函數,GC.SuppressFinalize,Dispose的最底層邏輯。當然這里還有很多技術問題需要解決。后面再看。TXH28資訊網——每日最新資訊28at.com

標記的作用

GC.SuppressFinalize問題來了,它的這些標記有什么用呢?這是一個非常繞的問題,分析下。首先的enum_flag_HasFinalizer標記表示當前類包含了析構函數,GC_ALLOC_FINALIZE標記表示當前的類對象需要填充到析構隊列里面去。

而BIT_SBLK_FINALIZER_RUN標記是最為重要的,它如果被標記了則表示從析構隊列里面溢出,不需要運行這個當前類的析構函數。TXH28資訊網——每日最新資訊28at.com

在GC的標記階段標記對象是否存活完成之后,它需要對對象的析構隊列進行掃描。如果析構隊列(SegQueue)里的對象被標記存活,且它的對象頭有TXH28資訊網——每日最新資訊28at.com

BIT_SBLK_FINALIZER_RUN標志,則表示此對象的析構隊列里的對象可以移出了,也就是不運行此對象的析構函數。TXH28資訊網——每日最新資訊28at.com

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

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

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: Docker容器化構建可擴展的分布式緩存系統:Memcached和Redis

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

標簽:
  • 熱門焦點
Top