【发布时间】:2019-02-15 14:47:52
【问题描述】:
我正在编写一些工具来帮助验证在运行时发出的 IL。此验证的一部分涉及在发出操作码时维护Stack<Type>,以便将来使用这些堆栈元素的操作码可以被验证为使用正确的类型。但是,我对如何处理 ldind.i 操作码感到困惑。
Microsoft 文档指出:
ldind.i 指令间接从 指定的地址(本机 int、& 或 * 类型)作为 本机 int。
在 C# 中,未定义原生 int,我对哪种类型最准确地表示此数据感到困惑。如何确定它的大小,以及应该使用哪种 C# 类型来表示它?我担心它会因系统硬件而异。
【问题讨论】:
-
它是 C# 中的 IntPtr。关于它的“原生”是它的大小根据进程位数而变化,32 位模式下为 4 个字节,64 位模式下为 8 个字节。使其能够存储指针。从 C# 程序获取 ldind.i 需要 fixed 关键字通过指针访问 IntPtr[] 数组。这是不可验证的不安全代码,没有边界检查。
-
那么,澄清一下,
ldind.i本质上是取消引用指向本机指针的本机指针?例如。堆栈上的地址是IntPtr**? -
不,IntPtr*。 IntPtr foo[] = 新的 IntPtr[1];固定 (IntPtr* p = &foo[0]) { var value = *p; }
-
更简单:IntPtr* p = null; var v = *p;