简体   繁体   English

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

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

In unsafe code in C#, I assigned a pointer to the managed variable of an array type:在 C# 的不安全代码中,我分配了一个指向数组类型托管变量的指针:

int[] array = new int[3];

// ...

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

Then I looked at corresponding part of the IL code:然后我查看了 IL 代码的相应部分:

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

Since this is unsafe code, and int* ptr is declaration of unmanaged pointer (or I think so at the moment), why in the CIL code doesn't write int32* ptr , instead of int32& ptr ?由于这是不安全的代码,并且int* ptr是非托管指针的声明(或者我现在这么认为),为什么在CIL代码中不写int32* ptr ,而不是int32& ptr

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

Page 334第 334 页

"1.1.5.2 Managed pointers (type &) "1.1.5.2 托管指针(类型&)

1.2 Managed pointers (&) can point to a local variable, a method argument, a field of an object, a field of a value type, an element of an array, a static field, or the address where an element just past the end of an array would be stored (for pointer indexes into managed arrays). 1.2托管指针 (&) 可以指向局部变量、方法参数、对象的字段、值类型的字段、数组的元素、静态字段或元素刚刚结束的地址将存储一个数组(用于托管数组的指针索引)。 Managed pointers cannot be null.托管指针不能为空。 (They shall be reported to the garbage collector, even if they do not point to managed memory)" (它们应报告给垃圾收集器,即使它们不指向托管内存)"

Page 149第 149 页

7.1.2 pinned 7.1.2 固定

The signature encoding for pinned shall appear only in signatures that describe local variables (§15.4.1.3). pinned 的签名编码应仅出现在描述局部变量的签名中(第 15.4.1.3 节)。 While a method with a pinned local variable is executing, the VES shall not relocate the object to which the local refers.在执行带有固定局部变量的方法时,VES 不应重新定位局部变量所指的对象。 That is, if the implementation of the CLI uses a garbage collector that moves objects, the collector shall not move objects that are referenced by an active pinned local variable.也就是说,如果 CLI 的实现使用移动对象的垃圾收集器,则收集器不应移动由活动固定局部变量引用的对象。 [Rationale: If unmanaged pointers are used to dereference managed objects, these objects shall be pinned. [基本原理:如果非托管指针用于取消引用托管对象,则这些对象应被固定。 This happens, for example, when a managed object is passed to a method designed to operate with unmanaged data.例如,当托管对象被传递给设计为使用非托管数据操作的方法时,就会发生这种情况。 end rationale]结束理由]

I agree with Hans as to the rational behind the msil language design choice.关于 msil 语言设计选择背后的理性,我同意 Hans 的观点。


These two things are different:这两件事是不同的:

int[] arry = new int[5];

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

vs.对比

int* ptr = stackalloc int[5];

If you look at the IL created for the second one, you'll see this (which I think is what you're expecting):如果您查看为第二个创建的 IL,您会看到这一点(我认为这是您所期望的):

.locals init ([0] int32* ptr)

In the first version (your version), you're pointing to an instance of System.Array (a managed type).在第一个版本(您的版本)中,您指向 System.Array 的一个实例(托管类型)。 In my version (using stackalloc) you're pointing to what I think you're expecting to point to... a block of memory large enough for 5 ints.在我的版本中(使用 stackalloc),您指向的是我认为您期望指向的内容……一块足够大的内存块可容纳 5 个整数。

ILDASM was written by a C++ programmer at Microsoft. ILDASM是由 Microsoft 的 C++ 程序员编写的。 A language where the difference between pointers and references are a big deal.一种语言,指针和引用之间的区别很大。 A C++ reference under the hood is also a pointer, but one that's guaranteed to never be null.引擎盖下的 C++ 引用也是一个指针,但它保证永远不会为空。 A reference is syntactically identified by &, a pointer is *.引用在语法上由 & 标识,指针是 *。

Which is the case here;这里就是这种情况; there is a difference between the pointer and the pointed-to value.指针和指向的值之间存在差异。 The pointed-to value may be null, but the reference to the pointer is never null.指向的值可能为空,但对指针的引用永远不会为空。 The "array" variable is guaranteed to be present in the stack frame and its reference thus have a non-null value. “数组”变量保证存在于堆栈帧中,因此其引用具有非空值。 Only its value might be null.只有它的可能为空。 Which happens when the array isn't initialized.当数组未初始化时会发生这种情况。 This level of indirection made pointers unpopular and largely absent in the C# language.这种间接级别使得指针在 C# 语言中不受欢迎并且基本上不存在。 And CS101.和 CS101。

C# is a managed coded language, so there will not be any pointers. C# 是一种托管编码语言,因此不会有任何指针。 But there is a wrapper class to use the pointers.但是有一个包装类来使用指针。 Maybe because of that, you are noticing some difference in these two.也许正因为如此,您会注意到这两者之间存在一些差异。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM