CIL: & # 8220; L'operazione potrebbe destabilizzare l'autonomia & # 8221; eccezione
-
03-07-2019 - |
Domanda
Ho giocato un po 'con PostSharp e ho riscontrato un brutto problema.
A seguito di IL nell'assemblaggio 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
}
attiva System.Security.VerificationException: l'operazione potrebbe destabilizzare il runtime. eccezione. Il riflettore lo analizza OK. Cosa potrebbe esserci di sbagliato in questo?
Aggiornamento 1 Il codice funziona come segue:
L_0018: ldloc.0
L_0019: ldc.i4.0
L_001a: ceq
L_001c: stloc.1
L_001d: ldloc.1
Aggiornamento 2 Ottengo un'eccezione specifica all'interno del setter stesso
Aggiornamento 3 Effettuare chiamate non statiche come callvirt (NotifyPropertyChanged) non aiuta
Aggiornamento 4 Commentare (a scopo di test) il codice:
.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
}
e sostituendo L_001e: brtrue.s L_002b con L_001e: br.s L_002b fa il trucco ma è un ritorno incondizionato - non quello che voglio.
Aggiornamento 5 Se uso il compilatore C # per imitare il comportamento richiesto (devo ancora farlo con Postsharp) Ottengo il seguente IL:
<*>Nota che ci sono differenze minori - salto extra di br.s su L_0016 e qualche strano salto L_001e: brtrue.s L_002b. Nella versione del compilatore ottengo il salto diretto per ret.
Soluzione
Hai usato peverify? Dovresti sempre eseguire questa utility quando giochi direttamente con MSIL (puoi usare il flag msbuild / p: PostSharpVerify = true).
Guardando il tuo codice:
-
Le variabili locali non sono inizializzate (parola chiave " init " mancante). Questa è una proprietà di MethodBodyDeclaration.
-
Stai usando un 'lasciare' invece di un 'jmp' fuori da un blocco protetto; questo è inutile ma non dovrebbe importare.
Buona fortuna
-gael
Altri suggerimenti
È difficile dirlo: hai una traccia dello stack? Questa eccezione viene generalmente generata quando il CLR non è in grado di verificare la sicurezza del tipo del codice. Poiché ciò potrebbe derivare da questo codice o da uno qualsiasi dei metodi o tipi che stai utilizzando, sarà difficile dire quale sia il problema senza una traccia dello stack.
Ecco un post che affronta questo errore. Non so se il tuo caso particolare sia causato dallo stesso problema, ma in generale sembra che questo abbia a che fare con la sicurezza e la verifica dell'accesso al codice. In tal caso, Reflector sarà in grado di leggere bene l'IL, ma il sistema CAS lo avvierà per motivi sconosciuti.
Sembra che tu abbia un setter di proprietà che chiama in un gruppo di altri oggetti. Dovresti passare attraverso quelle altre chiamate di metodo alla ricerca di grandi dichiarazioni switch, nel caso in cui si tratti del problema specifico menzionato nel post.