溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何驗(yàn)證fixed關(guān)鍵字效果

發(fā)布時(shí)間:2021-12-18 21:53:54 來(lái)源:億速云 閱讀:111 作者:柒染 欄目:編程語(yǔ)言

本篇文章為大家展示了如何驗(yàn)證fixed關(guān)鍵字效果,內(nèi)容簡(jiǎn)明扼要并且容易理解,絕對(duì)能使你眼前一亮,通過(guò)這篇文章的詳細(xì)介紹希望你能有所收獲。

之前談到String連接操作的性能,其中會(huì)涉及到unsafe操作,而unsafe操作必然會(huì)涉及到指針,于是fixed關(guān)鍵字也應(yīng)運(yùn)而生。fixed關(guān)鍵字是用來(lái)pin住一個(gè)引用地址的,因?yàn)槲覀冎繡LR的垃圾收集器會(huì)改變某些對(duì)象的地址,因此在改變地址之后指向那些對(duì)象的引用就要隨之改變。這種改變是對(duì)于程序員來(lái)說(shuō)是無(wú)意識(shí)的,因此在指針操作中是不允許的。否則,我們之前已經(jīng)保留下的地址,在GC后就無(wú)法找到我們所需要的對(duì)象。現(xiàn)在就來(lái)我們就來(lái)做一個(gè)小實(shí)驗(yàn),驗(yàn)證fixed關(guān)鍵字的效果。

當(dāng)然,這個(gè)實(shí)驗(yàn)很簡(jiǎn)單,簡(jiǎn)單地可能會(huì)讓您笑話。首先我們來(lái)準(zhǔn)備一個(gè)SomeClass類(lèi):

public class SomeClass  {      public int Field;  }

然后準(zhǔn)備一段代碼:

private static unsafe void GCOutOfFixedBlock()  {      var a = new int[100];      var c = new SomeClass();       fixed (int* ptr = &c.Field)      {          PrintAddress("Before GC", (int)ptr);      }       GC.Collect(2);       fixed (int* ptr = &c.Field)      {          PrintAddress("After GC", (int)ptr);      }  }   private static void PrintAddress(string name, int address)  {      Console.Write(name + ": 0x");      Console.WriteLine(address.ToString("X"));  }

在GCOutOfFixedBlock方法中,我們首先分配一個(gè)長(zhǎng)度為100的int數(shù)組,然后新建一個(gè)SomeClass對(duì)象。新建數(shù)組的目的在于制造“垃圾”,目的是在調(diào)用GC.Collect方法時(shí)改變SomeClass對(duì)象在堆中的位置。由于垃圾回收發(fā)生在fixed代碼塊之外,這樣我們前后兩次打印出的值便是不同的:

Before GC: 0x1A058C0
After GC: 0x1975DF4

值得注意的是,這段代碼必須在Release模式下進(jìn)行編譯,讓CLR執(zhí)行代碼時(shí)進(jìn)行優(yōu)化,這樣CLR便會(huì)在垃圾回收時(shí)發(fā)現(xiàn)a數(shù)組已經(jīng)是垃圾了(因?yàn)楹竺娴拇a不會(huì)用它),于是會(huì)將其回收——否則便無(wú)法看出地址改變的效果來(lái)。那么,我們重寫(xiě)一段代碼:

private static unsafe void GCInsideFixedBlock()  {      var a = new int[100];      var c = new SomeClass();       fixed (int* ptr = &c.Field)      {          PrintAddress("Before GC", (int)ptr);          GC.Collect(2);      }       fixed (int* ptr = &c.Field)      {          PrintAddress("After GC", (int)ptr);      }  }

結(jié)果如下:

Before GC: 0x1B558C0
After GC: 0x1B558C0

由于GC發(fā)生在fixed代碼塊內(nèi)部,因此c對(duì)象被pin在堆上了,于是GC前后c對(duì)象的地址沒(méi)變,這就是fixed的作用。那么,下面這段代碼運(yùn)行結(jié)果是什么呢?

private static unsafe void Mixed()  {      var a = new int[100];      var c1 = new SomeClass();      var c2 = new SomeClass();       fixed (int* ptr1 = &c1.Field)      {          PrintAddress("Before GC", (int)ptr1);      }       fixed (int* ptr2 = &c2.Field)      {          PrintAddress("Before GC (fixed)", (int)ptr2);          GC.Collect(2);      }       fixed (int* ptr1 = &c1.Field)      {          PrintAddress("After GC", (int)ptr1);      }       fixed (int* ptr2 = &c2.Field)      {          PrintAddress("After GC (fixed)", (int)ptr2);      }  }

上述內(nèi)容就是如何驗(yàn)證fixed關(guān)鍵字效果,你們學(xué)到知識(shí)或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識(shí)儲(chǔ)備,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI