CIL 和数组边界检查
让我们假设以下 CIL 程序:
.assembly extern mscorlib {}
.assembly Program {}
.method private static void Main() cil managed
{
.entrypoint
.maxstack 4
.locals init ( int32[] a,
uint32 t )
// Creates an array of int of size 10
ldc.i4 10
newarr int32
stloc.0
// Writes 0xaabbccdd at the index 2 of the array
ldloc.0
ldc.i4.2
ldc.i4 0xaabbccdd
stelem.i4
// Loads
ldloc.0
ldc.i4 9 // <HERE>
ldelem.i1
stloc.1
ldstr "Value: 0x{0:x8}"
ldloc.1
box [mscorlib]System.UInt32
call void [mscorlib]System.Console::WriteLine(string, object)
ret
}
该程序:
- 创建一个 int 大小为 10 的数组
- 在数组的索引 2 处写入 0xaabbccdd
- 尝试使用 ldelem.i1 读取数组中的一个字节
- 打印结果
诀窍是我使用“ldelem.i1”。 i1”而不是更标准的“idelem.i4”以解决性能问题(我想避免进行屏蔽),其想法是像 C 中的指针一样访问数组的数据。
但是事情不太好,因为当 ldelem.i1 的参数索引超过 10 时,程序会崩溃 (IndexOutOfRangeException)。 这使得这个技巧毫无用处,因为我无法访问第三个索引处的整数前半部分之后的数据。
理想情况下,我想访问索引 39 之前的字节,它对应于索引 9 处整数的最后一个字节。
如果有人对这一点有一些想法,我将非常感激。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
有趣的。 ECMA-335 规定,如果索引大于或等于数组的大小(这肯定是),它将引发异常。让我惊讶的不是抛出异常,而是索引首先被视为 int 数组中的 byte 索引 - 我可以'没有看到任何地方都指定了这一点。
我怀疑您进入了未指定行为的领域,很可能是不打算指定的行为 - 我怀疑您只是不打算使用
int
数组上的 >ldelem.i1。Interesting. The ECMA-335 states that it will throw an exception if the index is greater than or equal to the size of the array, which it definitely is. What surprises me about this isn't that the exception is thrown, but that the index is treated as a byte index into an int array in the first place - I can't see that that's specified anywhere.
I suspect you're into the realms of unspecified behaviour, quite possibly behaviour which isn't intended to be specified - I suspect you're just not meant to use
ldelem.i1
on anint
array.