有关 InvalidProgramException 的帮助(无效的 IL 代码?)
我在使用 System.Reflection.Emit
单声道导出的程序集中遇到了一个奇怪的错误。 当尝试运行我的程序集时,我收到一个 InvalidProgramException
:无效的 IL 代码。
monodis
给了我这个 CIL 结果(与我使用 Emit 导出的结果一致):
.method public static hidebysig
default void f_main (class [Pine.Core]Pine.Core.Function A_0, class [Pine.Core]Pine.Core.ValueList A_1) cil managed
{
// Method begins at RVA 0x2144
// Code size 26 (0x1a)
.maxstack 4
.locals init (
class [Pine.Core]Pine.Core.Function V_0,
class [Pine.Core]Pine.Core.IScope V_1,
class [Pine.Core]Pine.Core.ValueList V_2,
class [Pine.Core]Pine.Core.IScope V_3)
IL_0000: ldarg.0
IL_0001: stloc.0
IL_0002: ldarg.1
IL_0003: stloc.2
IL_0004: ldloc.0
IL_0005: ldftn instance class [Pine.Core]Pine.Core.IScope class [Pine.Core]Pine.Core.Function::get_Scope()
IL_000b: stloc.1
IL_000c: ldloc.1
IL_000d: newobj instance void class [Pine.Core]Pine.Core.BlockScope::'.ctor'(class [Pine.Core]Pine.Core.IScope)
IL_0012: stloc.3
IL_0013: ldloc.2
IL_0014: call instance void class [Pine.Core]Pine.Core.ValueList::Clear()
IL_0019: ret
} // end of method PineType::f_main
错误发生在 IL_000b: stloc.1
我不知道为什么。
我尝试用 pop 指令替换 stloc.1
。当我这样做时,错误发生在 IL_0019: ret
中,
我真的不知道为什么会这样。有什么想法吗?
附加信息:
IScope
是一个接口BlockScope
实现IScope
Function
有一个public IScope Scope { get;私人套装; 我在 Mono 2.6.7( Boehm
- , AMD64) 和 Mono 2.8(Boehm with typed GC and Parallel Mark, AMD64) 中都遇到了这个错误
I'm getting a weird bug in an assembly exported with System.Reflection.Emit
with mono.
When attempting to run my assembly, I get an InvalidProgramException
: Invalid IL code.
monodis
gives me this CIL result(which is consistent with what I export with Emit):
.method public static hidebysig
default void f_main (class [Pine.Core]Pine.Core.Function A_0, class [Pine.Core]Pine.Core.ValueList A_1) cil managed
{
// Method begins at RVA 0x2144
// Code size 26 (0x1a)
.maxstack 4
.locals init (
class [Pine.Core]Pine.Core.Function V_0,
class [Pine.Core]Pine.Core.IScope V_1,
class [Pine.Core]Pine.Core.ValueList V_2,
class [Pine.Core]Pine.Core.IScope V_3)
IL_0000: ldarg.0
IL_0001: stloc.0
IL_0002: ldarg.1
IL_0003: stloc.2
IL_0004: ldloc.0
IL_0005: ldftn instance class [Pine.Core]Pine.Core.IScope class [Pine.Core]Pine.Core.Function::get_Scope()
IL_000b: stloc.1
IL_000c: ldloc.1
IL_000d: newobj instance void class [Pine.Core]Pine.Core.BlockScope::'.ctor'(class [Pine.Core]Pine.Core.IScope)
IL_0012: stloc.3
IL_0013: ldloc.2
IL_0014: call instance void class [Pine.Core]Pine.Core.ValueList::Clear()
IL_0019: ret
} // end of method PineType::f_main
The error happens in IL_000b: stloc.1
I have no idea why.
I tried to replace the stloc.1
by a pop instruction. When I do that the error happens in IL_0019: ret
I really don't know why this is behaving like this. Any ideas?
Additional Information:
IScope
is an interfaceBlockScope
implementsIScope
Function
has apublic IScope Scope { get; private set; }
- I get this error with both Mono 2.6.7(Boehm, AMD64) and Mono 2.8(Boehm with typed GC and Parallel Mark, AMD64)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
编辑:从代码来看,也许 IL_0005 应该是 call/callvirt 而不是 ldftn ?也许发射使用了错误的操作码?
Local 1 是 IScope。 ldftn 将函数指针(本机 int)推送到计算堆栈上。 IL_000b 处的存储指令无法验证,因为本机 int 不可验证程序分配给 IScope。
至于你的第二个问题,你已经使用 IL_0004 处的指令使评估堆栈不平衡。 ldftn 的堆栈转换为“... -> ..., ftn”。这意味着它不需要评估堆栈参数,只需要立即元数据标记。通过将 IL_000b 更改为 pop,可以弹出 ldftn 推送的内容,而不是 IL_0004 推送的内容。
我不清楚的是你想要做什么。您不能将单个函数指针视为接口(至少在概念上您可以将其视为指向 v 表的指针)。您需要实例化一个实现该接口的类型。您可以对函数指针执行的操作是从中创建一个委托 - 委托具有 .ctor 的 (object, native int) 重载。这就是我假设 IL_0004 推送的对象引用将发挥作用的地方(此 .ctor 的第一个参数)。当然,您也可以直接调用函数指针。由于我不熟悉您正在交互的对象模型,因此我无法说出正确的方法是什么。
Edit: judging from the code, perhaps IL_0005 is meant to be a call/callvirt and not a ldftn? Perhaps the emitting is using the wrong opcode?
Local 1 is an IScope. ldftn pushes a function pointer (native int) onto the evaluation stack. The store instruction at IL_000b fails verifiability, as a native int is not verifier-assignable-to IScope.
As for your second problem, you've unbalanced the evaluation stack with the instruction at IL_0004. ldftn's stack transition is " ... -> ..., ftn". Meaning it doesn't take an evaluation stack argument, only the immediate metadata token. By changing IL_000b to a pop, you pop what ldftn pushed, but not what IL_0004 pushed.
What isn't clear to me is what you're attempting to do. You can't treat a single function pointer as an interface (which you could think of, conceptually at least, as a pointer to a v-table). You would need to instantiate a type that implements the interface. What you could do with the function pointer is create a delegate from it - Delegate has an (object, native int) overload for .ctor. That would be where I assume the object reference pushed by IL_0004 would come into play (first argument to this .ctor). You could, of course, calli the function pointer directly as well. As I am unfamiliar with this object model you're interacting with, I can't say what the right approach is.