';固定';C#中的语句和CIL代码中的托管指针

本文关键字:指针 代码 语句 固定 CIL | 更新日期: 2023-09-27 18:00:18

在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

';固定';C#中的语句和CIL代码中的托管指针

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

第334页

"1.1.5.2托管指针(类型和)

1.2托管指针(&)可以指向局部变量、方法参数、对象的字段,值的字段类型,数组的元素,静态字段,或元素所在的地址刚好过了数组的末尾已存储(用于指向的指针索引托管阵列)托管指针不能为null。(应报告给垃圾收集器,即使他们没有指向管理存储器)"

第149页

7.1.2固定

固定的签名编码应仅出现在描述局部变量的签名中(§15.4.1.3)。当执行带有固定局部变量的方法时,VES不得重新定位局部引用的对象也就是说,如果CLI的实现使用移动对象的垃圾收集器,则该收集器不应移动活动固定本地变量引用的对象。[基本原理:如果使用非托管指针来取消引用托管对象,则应固定这些对象。例如,当托管对象被传递给设计用于处理非托管数据的方法时,就会发生这种情况。end基本原理]

我同意汉斯关于msil语言设计选择背后的理性。


这两件事是不同的:

int[] arry = new int[5];
fixed (int* ptr = arry)
{
  ...
}

与。

int* ptr = stackalloc int[5];

如果你看看为第二个创建的IL,你会看到这个(我认为这是你所期望的):

.locals init ([0] int32* ptr)

在第一个版本(您的版本)中,您指向System.Array(托管类型)的一个实例。在我的版本中(使用stackalloc),你指向的是我认为你希望指向的……一个足够容纳5 int的内存块。

ILDASM是由微软的一位C++程序员编写的。一种指针和引用之间的差异很大的语言。隐藏的C++引用也是一个指针,但它保证永远不会为null。引用在语法上由&,指针是*。

这里的情况就是这样;指针和指向的值之间存在差异。指向的值可能为null,但对指针的引用永远不会为null。";阵列";变量保证存在于堆栈帧中,因此其引用具有非零值。只有其可能为null。当数组未初始化时会发生这种情况。这种间接级别使得指针在C#语言中不受欢迎,而且在很大程度上不存在。以及CS101。

C#是一种托管编码语言,因此不会有任何指针。但是有一个包装类可以使用指针。也许正因为如此,你才注意到这两者之间的一些差异。