簡體   English   中英

C# 中的“固定”語句和 CIL 代碼中的托管指針

[英]The 'fixed' statement in C# and managed pointer in CIL code

在 C# 的不安全代碼中,我分配了一個指向數組類型托管變量的指針:

int[] array = new int[3];

// ...

fixed (int* ptr = array)
{
    // Some code
}

然后我查看了 IL 代碼的相應部分:

.locals init ([0] int32[] 'array',
       [1] int32& pinned ptr)

由於這是不安全的代碼,並且int* ptr是非托管指針的聲明(或者我現在這么認為),為什么在CIL代碼中不寫int32* ptr ,而不是int32& ptr

http://www.ecma-international.org/publications/standards/Ecma-335.htm

第 334 頁

"1.1.5.2 托管指針(類型&)

1.2托管指針 (&) 可以指向局部變量、方法參數、對象的字段、值類型的字段、數組的元素、靜態字段或元素剛剛結束的地址將存儲一個數組(用於托管數組的指針索引)。 托管指針不能為空。 (它們應報告給垃圾收集器,即使它們不指向托管內存)"

第 149 頁

7.1.2 固定

pinned 的簽名編碼應僅出現在描述局部變量的簽名中(第 15.4.1.3 節)。 在執行帶有固定局部變量的方法時,VES 不應重新定位局部變量所指的對象。 也就是說,如果 CLI 的實現使用移動對象的垃圾收集器,則收集器不應移動由活動固定局部變量引用的對象。 [基本原理:如果非托管指針用於取消引用托管對象,則這些對象應被固定。 例如,當托管對象被傳遞給設計為使用非托管數據操作的方法時,就會發生這種情況。 結束理由]

關於 msil 語言設計選擇背后的理性,我同意 Hans 的觀點。


這兩件事是不同的:

int[] arry = new int[5];

fixed (int* ptr = arry)
{
  ...
}

對比

int* ptr = stackalloc int[5];

如果您查看為第二個創建的 IL,您會看到這一點(我認為這是您所期望的):

.locals init ([0] int32* ptr)

在第一個版本(您的版本)中,您指向 System.Array 的一個實例(托管類型)。 在我的版本中(使用 stackalloc),您指向的是我認為您期望指向的內容……一塊足夠大的內存塊可容納 5 個整數。

ILDASM是由 Microsoft 的 C++ 程序員編寫的。 一種語言,指針和引用之間的區別很大。 引擎蓋下的 C++ 引用也是一個指針,但它保證永遠不會為空。 引用在語法上由 & 標識,指針是 *。

這里就是這種情況; 指針和指向的值之間存在差異。 指向的值可能為空,但對指針的引用永遠不會為空。 “數組”變量保證存在於堆棧幀中,因此其引用具有非空值。 只有它的可能為空。 當數組未初始化時會發生這種情況。 這種間接級別使得指針在 C# 語言中不受歡迎並且基本上不存在。 和 CS101。

C# 是一種托管編碼語言,因此不會有任何指針。 但是有一個包裝類來使用指針。 也許正因為如此,您會注意到這兩者之間存在一些差異。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM