ЦИЛ:Исключение «Операция может дестабилизировать среду выполнения»

StackOverflow https://stackoverflow.com/questions/615530

Вопрос

Я немного поигрался с 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.В версии компилятора я получаю прямой переход к удалению.

Это было полезно?

Решение

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

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

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

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

Удачи,

-гаэль

Другие советы

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top