ЦИЛ:Исключение «Операция может дестабилизировать среду выполнения»
-
03-07-2019 - |
Вопрос
Я немного поигрался с 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).
Глядя на ваш код:
Ваши локальные переменные не инициализированы (отсутствует ключевое слово «init»).Это свойство MethodBodyDeclaration.
Вы используете «выход» вместо «jmp» из защищенного блока;это бесполезно, но не должно иметь значения.
Удачи,
-гаэль
Другие советы
Сложно сказать - есть ли у вас трассировка стека? Это исключение обычно выдается, когда CLR не может проверить безопасность типов вашего кода. Поскольку это могло произойти из этого кода или из любых методов или типов, которые вы используете, будет трудно сказать, в чем проблема без трассировки стека.
Вот сообщение, посвященное этой ошибке. Я не знаю, вызван ли ваш конкретный случай той же проблемой, но в целом похоже, что это связано с безопасностью и проверкой доступа к коду. Если это так, Reflector сможет прочитать IL просто отлично, но система CAS выкинет его по неизвестным причинам. Р>
Похоже, у вас есть установщик свойств, вызывающий кучу других объектов. Вам следует пройти через другие вызовы методов в поисках больших операторов switch, если это конкретная проблема, упомянутая в посте.