[英]CIL: “Operation could destabilize the runtime” exception
我一直在玩 PostSharp,但遇到了一个令人讨厌的问题。
在 Silverlight 组件中遵循 IL:
.method public hidebysig specialname newslot virtual final instance void
set_AccountProfileModifiedAt(valuetype [mscorlib]System.DateTime 'value') cil managed
{
.maxstack 2
.locals (
[0] bool ~propertyHasChanged,
[1] bool CS$4$0000)
L_0000: nop
L_0001: nop
L_0002: ldarg.0
L_0003: call instance valuetype [mscorlib]System.DateTime
Accounts.AccountOwner::get_AccountProfileModifiedAt()
L_0008: ldarg.1
L_0009: call bool [mscorlib]System.DateTime::op_Inequality(valuetype
[mscorlib]System.DateTime, valuetype [mscorlib]System.DateTime)
L_000e: stloc.0
L_000f: ldarg.0
L_0010: ldarg.1
L_0011: stfld valuetype [mscorlib]System.DateTime
Accounts.AccountOwner::accountProfileModifiedAt
L_0016: br.s L_0018
L_0018: ldloc.0
L_0019: ldc.i4.0
L_001a: ceq
L_001c: stloc.1
L_001d: ldloc.1
L_001e: brtrue.s L_002b
L_0020: ldarg.0
L_0021: ldstr "AccountProfileModifiedAt"
L_0026: call instance void
Accounts.AccountOwner::NotifyPropertyChanged(string)
L_002b: nop
L_002c: leave.s L_002e
L_002e: ret
}
触发 System.Security.VerificationException:操作可能会破坏运行时。 例外。 反射器解析它OK。 它有什么问题?
更新 1代码的工作原理如下:
public void set_AccountProfileModifiedAt(DateTime value)
{
bool propertyHasChanged = this.AccountProfileModifiedAt != value;
this.accountProfileModifiedAt = value;
if (propertyHasChanged)
{
this.NotifyPropertyChanged("AccountProfileModifiedAt");
}
}
更新 2我在设置器本身中得到指定的异常
更新 3作为 callvirt (NotifyPropertyChanged) 进行非静态调用没有帮助
更新 4注释掉(出于测试目的)代码:
L_0018: ldloc.0
L_0019: ldc.i4.0
L_001a: ceq
L_001c: stloc.1
L_001d: ldloc.1
并将 L_001e: brtrue.s L_002b 替换为 L_001e: br.s L_002b 可以解决问题,但它是无条件返回 - 不是我想要的。
更新 5如果我使用 C# 编译器来模拟所需的行为(我仍然需要使用 Postsharp 来做到这一点),我会得到以下 IL:
.method public hidebysig specialname newslot virtual final instance void
set_AccountProfileModifiedAt(valuetype [mscorlib]System.DateTime 'value') cil managed
{
.maxstack 2
.locals init (
[0] bool val,
[1] bool CS$4$0000)
L_0000: nop
L_0001: ldarg.0
L_0002: call instance valuetype [mscorlib]System.DateTime
Accounts.AccountOwner::get_AccountProfileModifiedAt()
L_0007: ldarg.1
L_0008: call bool [mscorlib]System.DateTime::op_Inequality(valuetype
[mscorlib]System.DateTime, valuetype [mscorlib]System.DateTime)
L_000d: stloc.0
L_000e: ldarg.0
L_000f: ldarg.1
L_0010: stfld valuetype [mscorlib]System.DateTime
Accounts.AccountOwner::accountProfileModifiedAt
L_0015: ldloc.0
L_0016: ldc.i4.0
L_0017: ceq
L_0019: stloc.1
L_001a: ldloc.1
L_001b: brtrue.s L_0029
L_001d: ldarg.0
L_001e: ldstr "AccountProfileModifiedAt"
L_0023: call instance void
Accounts.AccountOwner::NotifyPropertyChanged(string)
L_0028: nop
L_0029: ret
}
请注意有细微的差别 - 额外的 br.s 在 L_0016 处跳转和一些奇怪的跳转 L_001e: brtrue.s L_002b。 在编译器版本中,我可以直接跳转到 ret。
你用过peverify吗? 在直接使用 MSIL 时,您应该始终运行此实用程序(您可以使用 msbuild 标志 /p:PostSharpVerify=true)。
查看您的代码:
您的局部变量未初始化(缺少“init”关键字)。 这是 MethodBodyDeclaration 的一个属性。
您在受保护的块中使用“离开”而不是“jmp”; 这是没用的,但应该没关系。
很难说 - 你有堆栈跟踪吗? 当 CLR 无法验证代码的类型安全性时,通常会引发此异常。 由于这可能来自此代码或您正在使用的任何方法或类型,因此如果没有堆栈跟踪,将很难说出问题所在。
这是处理该错误的帖子。 我不知道您的特殊情况是否是由相同的问题引起的,但总的来说,这似乎与代码访问安全性和验证有关。 如果是这种情况,Reflector 将能够很好地读取 IL,但 CAS 系统会出于未知原因将其踢出。
看起来您有一个属性设置器调用了一堆其他对象。 您应该通过其他方法调用 go 寻找大开关语句,以防是帖子中提到的具体问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.