CIL :“운영은 런타임을 불안정화 할 수 있습니다”예외
-
03-07-2019 - |
문제
나는 PostSharp를 조금 가지고 놀았고 나는 불쾌한 문제에 부딪쳤다.
Silverlight 어셈블리에서 IL 다음 :
.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
}
Triggers 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는 트릭을 수행하지만 무조건적인 수익입니다.
업데이트 5C# 컴파일러를 사용하여 필요한 동작을 모방 한 경우 (여전히 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
}
L_0016에서의 추가 Br.s 점프 및 이상한 점프 L_001E : Brtrue.s L_002B. 컴파일러 버전에서는 RET로 직접 점프합니다.
해결책
Peverify를 사용 했습니까? MSIL로 직접 재생할 때는 항상이 유틸리티를 실행해야합니다 (MSBuild 플래그 /P : PostSharPverify = true).
코드보기 :
로컬 변수는 초기화되지 않았습니다 ( "Init"키워드 누락). 이것은 MethodBodyDeclaration의 속성입니다.
보호 된 블록에서 'JMP'대신 'Leave'를 사용하고 있습니다. 이것은 쓸모가 없지만 중요하지 않아야합니다.
행운을 빕니다,
-게일 사람
다른 팁
말하기 어렵다 - 스택 추적이 있습니까? 이 예외는 일반적으로 CLR이 코드의 유형 안전성을 확인할 수 없을 때 발생합니다. 이것은이 코드 나 사용중인 방법이나 유형에서 나올 수 있으므로 스택 추적이없는 문제가 무엇인지 말하기가 어렵습니다.
여기에 있습니다 그 오류를 다루는 게시물. 귀하의 특정 사례가 동일한 문제로 인해 발생하는지는 모르겠지만 일반적으로 코드 액세스 보안 및 검증과 관련이있는 것처럼 보입니다. 이 경우 반사판은 IL을 잘 읽을 수 있지만 CAS 시스템은 알려지지 않은 이유로 시작합니다.
다른 물체를 부르는 속성 세터가있는 것 같습니다. 게시물에 언급 된 특정 문제 인 경우 Big Switch 문을 찾는 다른 방법 호출을 살펴 봐야합니다.