日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
C#.Net析構(gòu)知識(shí)引申(CLR級(jí)的剖析)

一.前言

析構(gòu)函數(shù)是一個(gè)特殊的函數(shù),它有自己的線程,有自己的實(shí)現(xiàn)方式。在CLR里面相當(dāng)于一個(gè)小型的自我運(yùn)轉(zhuǎn)系統(tǒng)(有的書本把這個(gè)稱之為終結(jié)器)。來看下一些概念以及一些運(yùn)行模型。

創(chuàng)新互聯(lián)服務(wù)緊隨時(shí)代發(fā)展步伐,進(jìn)行技術(shù)革新和技術(shù)進(jìn)步,經(jīng)過10年的發(fā)展和積累,已經(jīng)匯集了一批資深網(wǎng)站策劃師、設(shè)計(jì)師、專業(yè)的網(wǎng)站實(shí)施團(tuán)隊(duì)以及高素質(zhì)售后服務(wù)人員,并且完全形成了一套成熟的業(yè)務(wù)流程,能夠完全依照客戶要求對網(wǎng)站進(jìn)行成都做網(wǎng)站、成都網(wǎng)站設(shè)計(jì)、建設(shè)、維護(hù)、更新和改版,實(shí)現(xiàn)客戶網(wǎng)站對外宣傳展示的首要目的,并為客戶企業(yè)品牌互聯(lián)網(wǎng)化提供全面的解決方案。

二.概述

析構(gòu)函數(shù)有一堆的概念
1.析構(gòu)對象列表(也就是存放了包含析構(gòu)函數(shù)的對象),它是最原始的。也就是當(dāng)進(jìn)行對象實(shí)例化分配的時(shí)候,會(huì)判斷此對象是否包含了析構(gòu)函數(shù),如果包含了,則把此對象添加到析構(gòu)對象列表。

flags & GC_ALLOC_FINALIZE

2.析構(gòu)空閑列表(FreeList==7,也即是不允許被調(diào)用的析構(gòu)函數(shù)所在的對象,這些對象存放在這個(gè)列表),它是C#里面一個(gè)著名的: GC.SuppressFinalize()來啟用,以不允許CLR調(diào)用虛構(gòu)函數(shù)。前提是首先這個(gè)對象里面包含了析構(gòu)函數(shù),然后才可以設(shè)置相應(yīng)的標(biāo)志位用以讓CLR不執(zhí)行此對象的析構(gòu)函數(shù)。并且GC運(yùn)行的時(shí)候也會(huì)需要這個(gè)對象沒有存活才可以放入到析構(gòu)空閑列表。

if (!obj->GetMethodTable ()->HasFinalizer())
    return;//這里如果對象不包含析構(gòu)函數(shù),則直接返回,即使啟用了GC.SuppressFinalize也毫無作用。
GCHeapUtilities::GetGCHeap()->SetFinalizationRun(obj);//這里給ObjectHeader設(shè)置BIT_SBLK_FINALIZER_RUN標(biāo)志,當(dāng)GC進(jìn)行掃描的時(shí)候,發(fā)現(xiàn)了這個(gè)標(biāo)志,并且此對象沒有被標(biāo)記存活,那么此對象就放入到析構(gòu)空閑列表

關(guān)于GC運(yùn)行的時(shí)候也會(huì)需要判斷這個(gè)對象沒有存活才可以放入到析構(gòu)空閑列表。

if (!g_theGCHeap->IsPromoted (obj))//GC運(yùn)想需要判斷此對象是否存活,不存活才可以進(jìn)行下一步
 {
  //然后會(huì)判斷是否包含了GC.SuppressFinalize設(shè)置的標(biāo)志,如果包含,則表示此對象的析構(gòu)函數(shù)不運(yùn)行運(yùn)行,把這個(gè)對象放入到空閑析構(gòu)隊(duì)列
  if ((obj->GetHeader()->GetBits()) & BIT_SBLK_FINALIZER_RUN)
  {
    MoveItem (i, Seg, FreeList);//把對象移動(dòng)到析構(gòu)空閑隊(duì)列
    obj->GetHeader()->ClrBit (BIT_SBLK_FINALIZER_RUN);//清除GC.SuppressFinalize設(shè)置的標(biāo)記
}

3.關(guān)鍵析構(gòu)函數(shù)列表堆(CriticalFinalizerListSeg==5這個(gè)隊(duì)列目前的情況不是太明了,尚未弄清它是做什么的,先擱置)

4.析構(gòu)列表堆(FinalizerListSeg==6,它存放的是需要被析構(gòu)線程調(diào)用的析構(gòu)函數(shù)所在的對象)

三.原理

了解了以上概念之后,我們來看下它這些隊(duì)列的內(nèi)存模型。首先要明確的一點(diǎn)是這些列表共用一個(gè)數(shù)組。CLR只是對這個(gè)數(shù)組進(jìn)行騷操作,用以區(qū)分析構(gòu)對對象列表,FreeList,CriticalFinalizerListSeg,FinalizerListSeg等四個(gè)隊(duì)列。

圖片

圖標(biāo)里面缺少一個(gè)析構(gòu)對象列表,那是因?yàn)槲鰳?gòu)對象列表頁是跟它們共用一個(gè)地址,也即是m_FillPointers數(shù)組值0x100地址。

它們?nèi)绾尾僮骱头峙淠?

1.當(dāng)對象進(jìn)行實(shí)例化的時(shí)候,把包含析構(gòu)函數(shù)的對象添加到析構(gòu)對象列.

2.當(dāng)析構(gòu)函數(shù)列表添加完畢之后,在進(jìn)行GC垃圾回收的時(shí)候。在標(biāo)記對象的動(dòng)作里面也即是mark_phase里,會(huì)對析構(gòu)對象列表進(jìn)行掃描。掃描的時(shí)候會(huì)進(jìn)行以下動(dòng)作。
首先,會(huì)獲取當(dāng)前GC堆代的起始地址。從這個(gè)起始地址開始遍歷循環(huán)到第三代結(jié)尾地址。在這個(gè)大循環(huán)前提下,里面有個(gè)小循環(huán)。小循環(huán)的作用是找出循環(huán)堆里面的析構(gòu)對象列表。也即是圖示的m_FillPointers數(shù)組的值。當(dāng)找到析構(gòu)對象列表,循環(huán)這個(gè)析構(gòu)對象列表里面的對象,判斷它是否存活,如果存活則不進(jìn)行處理。如果不存活,則分情況。分別會(huì)移動(dòng)到

FreeList,CriticalFinalizerListSeg,FinalizerListSeg等三個(gè)隊(duì)列。
FreeList也即是析構(gòu)空閑列表,它里面包含的對象的析構(gòu)函數(shù)永遠(yuǎn)不會(huì)被調(diào)用。FinalizerListSeg里面包含了被調(diào)用的析構(gòu)函數(shù)對象。CriticalFinalizerListSeg目的不明確,目前不清楚干什么。

3.當(dāng)掃描完畢完畢析構(gòu)對象列表之后,就會(huì)啟動(dòng)析構(gòu)線程。析構(gòu)線程會(huì)調(diào)用

FinalizerListSe列表和CriticalFinalizerListSe分別運(yùn)行里面的析構(gòu)函數(shù)。過程是:這個(gè)線程會(huì)判斷索引6也即是FinalizerListSe和索引5是否相等,如果不相等。則表示有析構(gòu)函數(shù)需要調(diào)用,把這個(gè)對象取出來,然后調(diào)用里面的析構(gòu)函數(shù)。然后會(huì)判斷索引5也即是

CriticalFinalizerListSe,跟FinalizerListSe同樣的方式.

4.RegisterForFinalization(注冊析構(gòu)函數(shù),也即是把有析構(gòu)函數(shù)的對象放到析構(gòu)列表)
ScanForFinalization(掃描析構(gòu)列表,也即是區(qū)分關(guān)鍵析構(gòu)列表堆,析構(gòu)空閑列表等)
GetNextFinalizableObject(調(diào)用析構(gòu)函數(shù))

四.析構(gòu)線程

析構(gòu)線程用的是windows事件內(nèi)核對象來操控的,這里舉一個(gè)簡單的例子

#include 
#include 
#include 


HANDLE g_hEvent;
UINT __stdcall ChildFunc(LPVOID);


int main(int argc, char* argv[])
{
  HANDLE hChildThread;
  UINT uId;


  // 創(chuàng)建一個(gè)自動(dòng)重置的(auto-reset events),未受信的(nonsignaled)事件內(nèi)核對象
  g_hEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);


  hChildThread = (HANDLE)::_beginthreadex(NULL, 0, ChildFunc, NULL, 0, &uId);


  // 通知子線程開始工作
  printf("Please input a char to tell the Child Thread to work: \n");
  getchar();
  ::SetEvent(g_hEvent);


  // 等待子線程完成工作,釋放資源
  ::WaitForSingleObject(hChildThread, INFINITE);
  printf("All the work has been finished. \n");
  ::CloseHandle(hChildThread);
  ::CloseHandle(g_hEvent);
  return 0;
}


UINT __stdcall ChildFunc(LPVOID)
{
  ::WaitForSingleObject(g_hEvent, INFINITE);
  printf("  Child thread is working...... \n");
  ::Sleep(5*1000); // 暫停5秒,模擬真正的工作
  return 0;
}

SetEvent通知線程進(jìn)行工作,那么析構(gòu)線程呢,則是CLR在某個(gè)時(shí)間段通知其進(jìn)行工作。具體的表現(xiàn)為,注冊析構(gòu)函數(shù),掃描析構(gòu)函數(shù),這兩步完成之后,就會(huì)通過SetEvent來通知析構(gòu)線程,你可以進(jìn)行工作了。此時(shí)析構(gòu)線程就會(huì)從析構(gòu)對象列表里面取出CriticalFinalizerListSe和FinalizerListSe來調(diào)用析構(gòu)函數(shù)。


當(dāng)前標(biāo)題:C#.Net析構(gòu)知識(shí)引申(CLR級(jí)的剖析)
文章起源:http://m.5511xx.com/article/cdjpsii.html