CIL: исключение "операция может дестабилизировать среду выполнения" - PullRequest
1 голос
/ 05 марта 2009

Я немного поиграл с PostSharp и столкнулся с неприятной проблемой.

После IL в сборке Silverlight:

.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: операция может дестабилизировать среду выполнения. исключение. Отражатель разбирает это нормально. Что может быть не так с этим?

Обновление 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.

Ответы [ 3 ]

2 голосов
/ 06 марта 2009

Вы использовали peverify? Вы всегда должны запускать эту утилиту, когда играете непосредственно с MSIL (вы можете использовать флаг msbuild /p:PostSharpVerify=true).

Глядя на ваш код:

  1. Ваши локальные переменные не инициализированы (отсутствует ключевое слово "init"). Это свойство MethodBodyDeclaration.

  2. Вы используете «выход» вместо «jmp» из защищенного блока; это бесполезно, но не должно иметь значения.

Удачи,

-gael

0 голосов
/ 05 марта 2009

Вот пост, который имеет дело с этой ошибкой. Я не знаю, вызван ли ваш конкретный случай той же проблемой, но в целом похоже, что это связано с безопасностью и проверкой доступа к коду. Если это так, Reflector сможет прочитать IL просто отлично, но система CAS выкинет его по неизвестным причинам.

Похоже, у вас есть установщик свойств, вызывающий кучу других объектов. Вам следует пройти через другие вызовы методов в поисках больших операторов switch, если это конкретная проблема, упомянутая в посте.

0 голосов
/ 05 марта 2009

Сложно сказать - есть ли у вас трассировка стека? Это исключение обычно выдается, когда CLR не может проверить безопасность типов вашего кода. Поскольку это могло произойти из этого кода или из любых методов или типов, которые вы используете, будет трудно сказать, в чем проблема без трассировки стека.

...