2011-02-24 2 views
2

모노로 System.Reflection.Emit으로 내 보낸 어셈블리에서 이상한 버그가 나타납니다. 내 어셈블리를 실행하려고하면 InvalidProgramException : IL 코드가 잘못되었습니다.InvalidProgramException 도움말 (잘못된 일리노이 코드)

.method public static hidebysig 
     default void f_main (class [Pine.Core]Pine.Core.Function A_0, class [Pine.Core]Pine.Core.ValueList A_1) cil managed 
{ 
    // Method begins at RVA 0x2144 
    // Code size 26 (0x1a) 
    .maxstack 4 
    .locals init (
     class [Pine.Core]Pine.Core.Function V_0, 
     class [Pine.Core]Pine.Core.IScope V_1, 
     class [Pine.Core]Pine.Core.ValueList V_2, 
     class [Pine.Core]Pine.Core.IScope V_3) 
    IL_0000: ldarg.0 
    IL_0001: stloc.0 
    IL_0002: ldarg.1 
    IL_0003: stloc.2 
    IL_0004: ldloc.0 
    IL_0005: ldftn instance class [Pine.Core]Pine.Core.IScope class [Pine.Core]Pine.Core.Function::get_Scope() 
    IL_000b: stloc.1 
    IL_000c: ldloc.1 
    IL_000d: newobj instance void class [Pine.Core]Pine.Core.BlockScope::'.ctor'(class [Pine.Core]Pine.Core.IScope) 
    IL_0012: stloc.3 
    IL_0013: ldloc.2 
    IL_0014: call instance void class [Pine.Core]Pine.Core.ValueList::Clear() 
    IL_0019: ret 
} // end of method PineType::f_main 

오류가 난 아무 생각이 왜 IL_000b: stloc.1에 발생합니다

monodis 나에게 (내가 방출 내보낼 것과 일치)이 CIL 결과를 제공합니다.

팝업 설명으로 stloc.1을 바꾸려고했습니다. 그럴 때 오류가 발생합니다. IL_0019: ret

저는 이것이 왜 이런 식으로 행동하는지 잘 모릅니다. 어떤 아이디어?

추가 정보 :

  • IScope
  • BlockScopeIScope
  • Functionpublic IScope Scope { get; private set; }
  • 내가 모노 2.6.7 (뵘, AMD64)와 모노 모두이 오류가 구현하는 인터페이스입니다 2.8 (Boehm with typed GC and Parallel Mark, AMD64)

답변

4

편집 : 코드에서 판단하면 IL_0005는 ldftn이 아닌 call/callvirt 일 수 있습니까? 아마도 발광이 잘못된 opcode를 사용하고 있습니까?

로컬 1은 IScope입니다. ldftn은 함수 포인터 (native int)를 평가 스택으로 푸시합니다. IL_000b의 스토어 명령은 검증 가능하지 않다. 네이티브 int는 검증 자 할당 가능이 아니기 때문에 IScope이다.

두 번째 문제는 IL_0004의 명령어로 평가 스택의 불균형을 해결했기 때문입니다. ldftn의 스택 전환은 "... -> ... ftn"입니다. 즉, 평가 스택 인수는 사용하지 않으며 즉각적인 메타 데이터 토큰 만 사용합니다. IL_000b를 팝으로 변경하면 ldftn이 푸시 한 것을 팝하지만 IL_0004가 푸시 한 것을 팝하지 않습니다.

나에게 분명하지 않은 것은 당신이하려는 일입니다. 하나의 함수 포인터를 인터페이스로 취급 할 수는 없습니다 (적어도 개념적으로는 v 테이블에 대한 포인터라고 생각할 수 있습니다). 인터페이스를 구현하는 유형을 인스턴스화해야합니다. 함수 포인터로 할 수있는 일은 delegate를 생성하는 것입니다 - Delegate는 .ctor에 대한 (객체, 기본 int) 오버로드를가집니다. 이것은 IL_0004에 의해 밀어 붙여진 객체 참조가 작동하게 될 것이라고 가정합니다 (이 .ctor에 대한 첫 번째 인수). 물론 함수 포인터를 직접 호출 할 수도 있습니다. 내가이 객체 모델에 익숙하지 않아 상호 작용을하고 있기 때문에 올바른 접근 방식이 무엇인지 말할 수는 없습니다.