vld*_*jcc 6 c# pointers cil unmanaged fixed
在C#中的不安全代码中,我分配了指向数组类型的托管变量的指针:
int[] array = new int[3];
...
fixed (int* ptr = array)
{
//some code
}
Run Code Online (Sandbox Code Playgroud)
然后我查看了IL代码的相应部分:
.locals init ([0] int32[] 'array',
[1] int32& pinned ptr)
Run Code Online (Sandbox Code Playgroud)
我想知道,因为这是不安全的代码,并且int* ptr是非托管指针的声明(或者我现在这么认为),为什么在IL代码中不写int32* ptr,而不是int32& ptr?
http://www.ecma-international.org/publications/standards/Ecma-335.htm
\n\n第334页
\n\n\n\n\n"1.1.5.2 托管指针(& 类型)
\n\n1.2托管指针 (&) 可以指向局部变量、方法参数、对象的字段、值类型的字段、数组的元素、静态字段或其中的地址将存储刚刚超过数组末尾的元素(用于托管数组中的指针索引)。托管指针\n不能为空。(即使它们不指向托管内存,也应将它们报告给垃圾收集器)”
\n
第 149 页
\n\n\n\n\n7.1.2 固定
\n\n固定的签名编码应仅出现在描述局部变量的签名中 (\xc2\xa715.4.1.3)。当具有固定局部变量的方法正在执行时,VES 不应重新定位局部引用的对象。也就是说,如果 CLI 的实现使用移动对象的垃圾收集器,则收集器不应移动由活动固定局部变量引用的对象。\n [基本原理:如果使用非托管指针取消引用托管对象,则这些对象应被固定。例如,当将托管对象传递给设计用于操作非托管数据的方法时,就会发生这种情况。结束理由]
\n
我同意 Hans 的观点,认为 msil 语言设计选择背后的合理性。
\n\n这两件事是不同的:
\n\nint[] arry = new int[5];\n\nfixed (int* ptr = arry)\n{\n ...\n}\nRun Code Online (Sandbox Code Playgroud)\n\n与
\n\nint* ptr = stackalloc int[5];\nRun Code Online (Sandbox Code Playgroud)\n\n如果您查看为第二个创建的 IL,您将看到以下内容(我认为这正是您所期望的):
\n\n.locals init ([0] int32* ptr)\nRun Code Online (Sandbox Code Playgroud)\n\n在第一个版本(您的版本)中,您指向 System.Array (托管类型)的实例。在我的版本(使用 stackalloc)中,您指向的是我认为您期望指向的内容...一块足够大的内存块,可容纳 5 个整数。
\n