CIL: exception «L'opération pourrait déstabiliser le runtime»
-
03-07-2019 - |
Question
Je joue un peu avec PostSharp et je suis tombé sur un vilain problème.
Après l'IL dans l'assemblage 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$4public void set_AccountProfileModifiedAt(DateTime value)
{
bool propertyHasChanged = this.AccountProfileModifiedAt != value;
this.accountProfileModifiedAt = value;
if (propertyHasChanged)
{
this.NotifyPropertyChanged("AccountProfileModifiedAt");
}
}
)
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
}
déclenche une exception System.Security.VerificationException: l'opération pourrait déstabiliser l'exécution. exception. Le réflecteur l’analyse bien. Qu'est-ce qui ne va pas avec ça?
Mise à jour 1 Le code est conçu pour fonctionner comme suit:
L_0018: ldloc.0
L_0019: ldc.i4.0
L_001a: ceq
L_001c: stloc.1
L_001d: ldloc.1
Mise à jour 2 Je reçois une exception spécifiée à l'intérieur du séparateur lui-même
Mise à jour 3 Faire des appels non statiques en tant que callvirt (NotifyPropertyChanged) n’aide en rien
Mise à jour 4 Code de commentaire (à des fins de test):
.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<*>)
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
}
et en remplaçant L_001e: brtrue.s L_002b par L_001e: br.s L_002b fait l'affaire mais c'est un retour inconditionnel - pas ce que je veux.
Mise à jour 5 Si j'utilise un compilateur C # pour imiter le comportement requis (je dois quand même le faire avec Postsharp) Je reçois l'IL suivant:
<*>Notez qu'il existe des différences mineures - saut supplémentaire br.s à L_0016 et étrange saut L_001e: brtrue.s L_002b. Dans la version du compilateur, je reçois un saut direct sur Ret.
La solution
Avez-vous utilisé peverify? Vous devez toujours exécuter cet utilitaire lorsque vous jouez directement avec MSIL (vous pouvez utiliser le drapeau msbuild / p: PostSharpVerify = true).
En regardant votre code:
-
Vos variables locales ne sont pas initialisées (mot-clé "init" manquant). C’est une propriété de MethodBodyDeclaration.
-
Vous utilisez un "congé" au lieu d'un "jmp" d'un bloc protégé; c'est inutile mais cela ne devrait pas avoir d'importance.
Bonne chance,
-gael
Autres conseils
Il est difficile de dire - avez-vous une trace de pile? Cette exception est généralement levée lorsque le CLR est incapable de vérifier la sécurité de type de votre code. Comme cela pourrait provenir de ce code ou de l’une des méthodes ou types que vous utilisez, il sera difficile de dire quel est le problème sans trace de pile.
Voici un article traitant de cette erreur. Je ne sais pas si votre cas particulier est causé par le même problème, mais en général, cela semble lié à la sécurité et à la vérification de l'accès au code. Si tel est le cas, Reflector sera en mesure de lire l’IL parfaitement, mais le système CAS le rejettera pour des raisons inconnues.
Il semble que vous ayez un configurateur de propriété appelant un groupe d’autres objets. Vous devriez passer par ces autres appels de méthode à la recherche de grandes instructions switch, au cas où ce soit le problème spécifique mentionné dans le message.