2017-10-25 2 views
5

다음과 같은 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, 코드가 작동 -하지만 이들 중 어느 것도, 내 지식, 그들이 코드에 존재하는 인 경우에 비해, 스택의 균형을 변경해야합니다 .여기

는 IL 코드 ILSpy와 C 번호로 디 컴파일 같습니다

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 내가 디버깅있어 프로그램이 호환되지 않습니다 ... 슬프게도

+1

ILSpy에서 컴파일 된 DLL을 열 때 볼 수있는 코드가 표시됩니까? (아마 일리노이보기에서만 - 아마 내가 C#으로 디 컴파일하지 않을 것입니다.) – xxbbcc

+2

슬프게도 이걸 재현 할 수 없습니다. 'ldarg.0'을 호출해야합니까? – IllidanS4

+2

peverify.exe를 어떻게 사용할 수 있는지 명확하지 않지만 localloc을 좋아하지 않습니다. 그 ldarg.0 스택의 불균형, 당신은 List <>의 기본 생성자를 호출하고 있습니다. 그냥 삭제하십시오. –

답변

2

,

모두가 노력하고 있습니다 ... 나는 CLR 버그에 충돌 보인다 기존 JIT 컴파일러를 사용하는 경우 :

set COMPLUS_useLegacyJit=1

나는이 문제를 일으킬 수있는 특정 RyuJit 설정을 분리 할 수 ​​없습니다. 본 기사의 권장 사항을 따랐습니다.
https://github.com/Microsoft/dotnet/blob/master/Documentation/testing-with-ryujit.md

도움을 주신 모든 분들께 감사드립니다!

+2

당신은 문제를 열 ​​수 있습니다. CoreCLR 저장소 (RyuJIT 포함); 이미'localloc'에 대한 몇 가지 (https://github.com/dotnet/coreclr/search?type=Issues) 있습니다.'localloc'은 'finally'에 허용되지 않으므로 지터가 혼란스러워서 여기에 완전히 들어 가지 않을 수도 있습니다. –

+0

@ JeroenMostert 감사합니다! 나는 이것이 사실일지도 모른다는 것을 의심한다. .NET 4.6에서 실행 중이므로 최신 CoreCLR에서 재생산되는지 확인한다. 이미 수정 된 유사한 버그가 발견되었으므로 가능성이 있습니다. 이미 수정되었을 수도 있습니다. https://github.com/dotnet/coreclr/blob/master/tests/src/JIT/Regression/VS- ia64-JIT/V1.2-M01/b10841/repro_good.il – valiano

+0

좋은 캐치! 버그의 원인이 무엇인지 궁금하네요. – IllidanS4