다음과 같은 CIL 코드가 있습니다.왜 localloc이이 CIL 메소드를 중단합니까?
.method assembly hidebysig specialname rtspecialname
instance void .ctor(class [mscorlib]System.Collections.Generic.IEnumerable`1<class System.Windows.Input.StylusDeviceBase> styluses) cil managed
{
.locals init (class [mscorlib]System.Collections.Generic.IEnumerator`1<class System.Windows.Input.StylusDeviceBase> V_0,
class System.Windows.Input.StylusDeviceBase V_1)
ldc.i4.8 // These instructions cause CIL to break
conv.u //
localloc //
pop //
ldarg.0
newobj instance void class [mscorlib]System.Collections.Generic.List`1<class System.Windows.Input.StylusDevice>::.ctor()
call instance void class [mscorlib]System.Collections.ObjectModel.ReadOnlyCollection`1<class System.Windows.Input.StylusDevice>::.ctor(class [mscorlib]System.Collections.Generic.IList`1<!0>)
ldarg.1
callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1<!0> class [mscorlib]System.Collections.Generic.IEnumerable`1<class System.Windows.Input.StylusDeviceBase>::GetEnumerator()
stloc.0
.try
{
leave.s IL_0040
}
finally
{
endfinally
}
IL_0040: ret
} // end of method StylusDeviceCollection::.ctor
내 질문에, 왜이 CIL 코드가 잘못입니다 : InvalidProgramException이 CLR에 의해 발생되고있는이 CIL 방법을 실행
?
여러 가지 이유 :
- localloc
을 제거하면 코드가 제대로 실행됩니다. 내 지식에 따르면 localloc
은 스택의 매개 변수 크기를 주소로 바꿔서 스택이 균형을 유지합니다 (AFAICT).
- try 및 finally 블록이 제거되면 코드가 제대로 실행됩니다.
- localloc
을 포함하는 첫 번째 명령어 블록을 try-finally 블록 다음으로 이동하면 코드가 올바르게 실행됩니다.
그래서 localloc과 try-finally의 조합에있는 것처럼 보입니다.
은 어떤 배경 :
내가 InvalidProgramException 후이 지점에 도착 인해 런타임에 만든 일부 기기에 원래 방법에 대한 던져졌다. 파악을 위해,이 디버깅에 대한 나의 접근 방식은 무엇을하는 것은, 계측 잘못이다 :
- 은 수정에서 DLL을 재 작성 부수는 방법
- 에 계측 코드를 적용
ildasm
- 로 결함이있는 DLL을 분해 IL은
ilasm
- 프로그램을 다시 실행하고, 검증과는
- 보관할 문제를 일으키는 최소한의 시나리오까지, gradualy 무너지는 방법의 IL 코드를 감소 (그리고 int로하지 않으려 고 노력 충돌 도중에 벌레 잡기 ...)
불행히도 peverify.exe /IL
은 오류를 나타내지 않았습니다. ECMA 사양과 Serge Lidin의 전문가 .NET IL 책을 콘솔에 넣으려고했으나 잘못된 점이 무엇인지 파악할 수 없었습니다.
내가 누락 된 기본적인 것이 있습니까?
편집 : 나는 약간 (지시 사항을 수정하지 않고) 더 완벽하게, 문제의 IL 코드를 업데이트
. ldarg
, newobj
등의 두 번째 명령 블록은 원래 코드 인 작업 코드에서 그대로 사용됩니다.
무엇을 나에게 이상한입니다, 하나 localloc
또는 .try
제거하여 - finally
, 코드가 작동 -하지만 이들 중 어느 것도, 내 지식, 그들이 코드에 존재하는 인 경우에 비해, 스택의 균형을 변경해야합니다 .여기
internal unsafe StylusDeviceCollection(IEnumerable<StylusDeviceBase> styluses)
{
IntPtr arg_04_0 = stackalloc byte[(UIntPtr)8];
base..ctor(new List<StylusDevice>());
IEnumerator<StylusDeviceBase> enumerator = styluses.GetEnumerator();
try
{
}
finally
{
}
}
편집 2
자세히 관찰 :
- IL 코드 localloc
블록 복용과 끝으로 이동 코드가 잘 돌아갑니다. 코드 자체는 괜찮습니다.
- 비슷한 IL 코드를 hello world 테스트 기능에 붙여 넣을 때 문제가 발생하지 않습니다. 나는 매우 당황 해요
...
은 내가 InvalidProgramException에서 더 많은 정보를 얻을 수있는 방법이 있었으면 좋겠어. CLR이 정확한 실패 이유를 예외 개체에 첨부하지 않는 것 같습니다. 나는 또한 CoreCLR의 디버그 빌드와 디버깅을 생각했지만, unforunately 내가 디버깅있어 프로그램이 호환되지 않습니다 ... 슬프게도
ILSpy에서 컴파일 된 DLL을 열 때 볼 수있는 코드가 표시됩니까? (아마 일리노이보기에서만 - 아마 내가 C#으로 디 컴파일하지 않을 것입니다.) – xxbbcc
슬프게도 이걸 재현 할 수 없습니다. 'ldarg.0'을 호출해야합니까? – IllidanS4
peverify.exe를 어떻게 사용할 수 있는지 명확하지 않지만 localloc을 좋아하지 않습니다. 그 ldarg.0 스택의 불균형, 당신은 List <>의 기본 생성자를 호출하고 있습니다. 그냥 삭제하십시오. –