【发布时间】:2015-03-04 14:33:43
【问题描述】:
我在 CIL 中定义了一个字段,如下所示:
.field public int32 modopt(void*) fld
我把它编译成一个程序集。现在我把它改成:
.field public int32 modopt(int16) fld
ILDASM 现在怎么可能报告(当显示为十六进制时)两个这两个字段?
Field #1 (04000001)
-------------------------------------------------------
Field Name: fld (04000001)
Flags : [Public] (00000006)
CallCnvntn: [FIELD]
Field type: CMOD_OPT 1b000001 I4
Signature : 06 20 06 08
此代码查找完全相同的两个字段(实际上我创建了第二个字段以匹配报告的签名)。签名显然与第二个字段匹配,但第一个字段的签名应该是这样的:06 20 0f 01 08!我在这里错过了什么?
编辑:
C# 不能发出这种类型的字段,抛出关于自定义类型修饰符不支持的指针和数组类型的异常,因此这显然解决了签名不匹配的问题。但是为什么 ILDASM 允许创建无法反编译的无效签名的问题仍然存在。
编辑#2:
似乎 ILASM 实际上正在创建正确的 IL,我上次错过的十六进制转储有所不同:
//the first assembly
TypeSpec #1 (1b000001)
-------------------------------------------------------
TypeSpec : Ptr Void
Signature: 0f 01
//the second assembly
TypeSpec #1 (1b000001)
-------------------------------------------------------
TypeSpec : I2
Signature: 06
所以在 ILDASM 十六进制转储中只有一个错误报告了错误的成员签名(尽管我想知道错误签名中的 06 来自哪里)。
【问题讨论】:
-
问一个显而易见的问题:是什么让你认为它应该是
06 20 0f 01 08?是否有细分/参考? -
@Marc 我查看了 CLI 的 ECMA。 modopt的元素类型为
20,指针的元素类型为0f,void为01。所以,把所有这些放在一起,modopt(void*)的签名应该是20 0f 01(06是字段 callconv,08是 int32)。 -
这是 C# 吗?我看到了 void* !
-
@niceman 不,它是 CIL
-
@niceman
void*在 C# 中与在 C++ 中一样有效。它也可以是任意数量的其他语言(包括手动编写的 CIL)。