【问题标题】:CIL: "Operation could destabilize the runtime" exceptionCIL:“操作可能会破坏运行时”异常
【发布时间】:2009-03-05 16:25:29
【问题描述】:

我一直在玩 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。

【问题讨论】:

    标签: c# silverlight clr postsharp cil


    【解决方案1】:

    你用过 peverify 吗?直接使用 MSIL 时应始终运行此实用程序(您可以使用 msbuild 标志 /p:PostSharpVerify=true)。

    查看您的代码:

    1. 您的局部变量未初始化(缺少“init”关键字)。这是 MethodBodyDeclaration 的一个属性。

    2. 您在受保护块之外使用“离开”而不是“jmp”;这是没用的,但应该没关系。

    【讨论】:

      【解决方案2】:

      很难说 - 你有堆栈跟踪吗?当 CLR 无法验证代码的类型安全性时,通常会引发此异常。由于这可能来自此代码或您正在使用的任何方法或类型,因此如果没有堆栈跟踪,将很难说出问题所在。

      【讨论】:

      • 栈顶只是一个属性设置器 :( : System.Security.VerificationException: Operation could destabilize the runtime. at Domain.Accounts.AccountOwner.set_AccountProfileModifiedAt(DateTime value)
      【解决方案3】:

      Here's 处理该错误的帖子。我不知道您的特殊情况是否是由相同的问题引起的,但总的来说,这似乎与代码访问安全性和验证有关。如果是这种情况,Reflector 将能够很好地读取 IL,但 CAS 系统会出于未知原因将其踢出。

      看起来你有一个属性设置器调用了一堆其他对象。您应该通过其他方法调用来寻找大的 switch 语句,以防是帖子中提到的具体问题。

      【讨论】:

      • 这就是它的样子: bool propertyHasChanged = this.AccountProfileModifiedAt != value; this.accountProfileModifiedAt = 值; if (propertyHasChanged) { this.NotifyPropertyChanged("AccountProfileModifiedAt");如果其他方法失败,IMO 它不应该在 setter 中失败?
      • 异常可能是由您正在访问的其他方法/属性之一引起的。作为测试,尝试将所有代码从 setter 中提取出来,看看是否可以修复它。然后一点一点地添加代码,找出到底是什么失败了。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-08-22
      • 2012-11-05
      • 1970-01-01
      • 1970-01-01
      • 2010-09-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多