我正在使用第 3 方库 JInt(JavaScript 解释器),它工作正常,直到我切换到 Mac OS X,之后我不断收到 ArgumentNullExceptions,经过一些调查,我发现 JInt 使用动态代码生成制作某种 Js-Clr 桥。该方法最后有以下说明:
code.Emit(OpCodes.Ldnull);
FieldInfo fieldInfo = typeof(JsUndefined).GetField("Instance");
code.Emit(OpCodes.Ldfld, fieldInfo);
以下是这些行的执行方式(全尺寸截图此处)
可以清楚地看到 fieldInfo
参数不为空,尽管当涉及到执行这些行,请注意 LDFLD 没有参数! (全尺寸屏幕截图此处):
我当前要执行的语句是 Ldnull,我执行“Step In”(Over Ldnull),并且 Ldfld 上发生 BANG 异常(全尺寸屏幕截图 此处)::
有什么建议吗?
I'm using 3rd party library JInt (the JavaScript interpriter) which was working fine until I've switched to Mac OS X, after that I keep on getting ArgumentNullExceptions, after some investigation I've found out that JInt uses dynamic code generation for making some sort of Js-Clr bridge. This method has the following instructions in the end:
code.Emit(OpCodes.Ldnull);
FieldInfo fieldInfo = typeof(JsUndefined).GetField("Instance");
code.Emit(OpCodes.Ldfld, fieldInfo);
Here's how these lines are executed (Full size screenshot here)
It is clearly seen that fieldInfo
argument is not null, though when it comes to executing these lines, notice that LDFLD has no argument! (Full size screenshot here):
My current statement that will get executed is Ldnull, I performing "Step In"(Over Ldnull) and BANG exception occurs over Ldfld (Full size screenshot here)::
Any suggestions?
发布评论
评论(2)
您描述的这个问题是不同问题的组合:
IL 反汇编不显示字段操作数。它不仅适用于您的领域,您可以在 ldsfld 之前的反汇编中看到它。我不担心这一点,但我鼓励您报告它有一个 MonoDevelop 错误。
JInt 使用一种奇怪的模式在堆栈上加载静态字段。我可以通过发出此模式在 Mono 2.10.6 上重现该问题和 NRE。好消息是它已在 master 中修复。由于您有权访问 JInt 的代码,为了防止 NRE,您可以修改 else 分支以简单地读取:
code.Emit(OpCodes.Ldsfld, typeof(JsUndefined).GetField("Instance"));
这会让你继续前进。
This issue you describe is a combination of different issues:
The IL disassembly doesn't show the fields operands. It's not only for your field, you can see it in the disassembly before for a ldsfld. I'd not worry about that, I encourage you to report it has a MonoDevelop bug though.
JInt is using a weird pattern to load a static field on the stack. I can reproduce the issue and the NRE on Mono 2.10.6 by emitting this pattern. Good news is that it is fixed in master. As you have access to JInt's code, to prevent the NRE, you can modify the else branch to simply read:
code.Emit(OpCodes.Ldsfld, typeof(JsUndefined).GetField("Instance"));
This will get you going.
ldfld 应该始终带有一个参数,否则您会得到一个无效的 CLR,并且运行时环境应该拒绝加载它(具有格式错误的 CIL 的程序集在加载时会抛出异常)。
我相信,由于某种原因,作为此 ldfld 参数的字段引用无法在运行时解析(尽管它在创建代码时存在)。一方面,这就是为什么您在 IDE 中得到不带参数的 ldfld(它不显示类型,因为它无法加载它),另一方面,您在执行此命令时得到 null 异常特定线路。
您确定动态创建的程序集正确引用了包含
JsUndefine
类型的程序集吗?代码生成器可以看到它,但是生成的代码能看到它吗?The
ldfld
should always come with an argument, otherwise you get an invalid CLR and the runtime environment should refuse to load it (assemblies with malformed CIL throw exceptions upon loading).I believe then that for some reason the field reference which is an argument of this
ldfld
cannot be resolved in the run time (although it exists when the code is created). On one hand this is why you get theldfld
without arguments in the IDE (it doesn't show the type because it is unable to load it) and on the other hand you get null exception upon executing this particular line.Are you sure that the dynamically created assembly correctly references the assembly containing the
JsUndefined
type? The code generator could be able to see it but the does the generated code see it?