2013-09-23 2 views
1

.NET에서 Reflect & 방출을 사용하여 동적 어셈블리를 생성하려고합니다. "Common Language Runtime이 잘못된 프로그램을 발견했습니다."라는 오류 메시지가 나타납니다. 난 하드 코딩 된 형식을 사용하여 원하는 기능을 가진 다른 프로그램을 만들었습니다. 작성하려고하는 기능은 궁극적으로 동적 유형을 사용하지만 ILDasm을 사용하여 생성해야하는 IL을 볼 수 있습니다. 나는 컴파일러가 생성하는 일리노이와 생성하고있는 일리노이를 비교하고있다. 내가 컴파일러가 생성 한 코드에 추가 항목이보고 한 방법의 .locals 초기화 선언에서CLR IL - .locals 초기화에 대괄호 대괄호

컴파일러가 생성 :

.locals init ([0] class [System.Core]System.Linq.Expressions.ParameterExpression CS$0$0000, 
      [1] class [System.Core]System.Linq.Expressions.ParameterExpression[] CS$0$0001) 

내 :

.locals init (class [System.Core]System.Linq.Expressions.ParameterExpression V_0, 
     class [System.Core]System.Linq.Expressions.ParameterExpression[] V_1) 

내가 돈 ' 컴파일러가 생성 한 코드에서 "[0]"과 "[1]"의 중요성을 이해해야합니다. 아무도 그것이 무엇을 의미하는지 말할 수 있습니까?

더 일반적인 질문으로, 나는 많은 문제없이 대부분의 ILDasm 출력을 따라갈 수 있습니다. 그러나 때로는 문제가되는 표현을 자주 접하게됩니다. 예를 들어,

callvirt instance class [EntityFramework]System.Data.Entity.ModelConfiguration.EntityTypeConfiguration`1<!!0> [EntityFramework]System.Data.Entity.DbModelBuilder::Entity<class DynamicEdmxTrial.HardFooAsset>() 

ILDASM

에서이 라인에서 "!! 0"아마도 법인 <>의 제네릭 형식을 의미한다, 그러나 나는 확실히 알 수없고, 나는 키가 궁금해 더 희미한 출력을 내게 설명하는 ILDasm 출력.

+2

"Common Language Runtime에서 잘못된 프로그램을 발견했습니다." "어셈블리에서 PEVerify를 실행 해 보셨습니까? – svick

+0

또한 정확히 어떻게 그'.local '을 얻고 있습니까? 둘 다 ILDasm에서 왔습니까? – svick

+0

"잘못된 프로그램"에 대해서는별로 신경 쓰지 않습니다. 나는 그것을 발견했다고 생각한다. 두 가지 .local 선언은 ILDasm에서 나왔습니다. 그것은 분명히 C# 코드와 Reflection.Emit 사이에 약간의 차이점을 발견했습니다. – jrv

답변

1

사양은 자유롭게 사용할 수 있습니다 here. 조금 익숙해 지지만 일단 구조를 파악하면 대부분의 세부 사항을 쉽게 찾을 수 있습니다. C 번호는 f<T, U>(), !!0T 것 부를 것이다, 그리고 !!1U 될 것이라고하는 방법 내부, 즉

Type ::=  | Description        | Clause 
    ‘!’ Int32 | Generic parameter in a type definition, | §II.9.1 
       | accessed by index from 0    | 
| ‘!!’ Int32 | Generic parameter in a method   | §II.9.2 
       | definition, accessed by index from 0 | 
... 

:

!!II.7.1 유형에 나열되어 있습니다.

그러나 [0]은 좋은 질문입니다. 명세는 그것을 다루는 것 같지 않습니다. .locals 지시어는

MethodBodyItem ::= ... 
| .locals [ init ] ‘(’ LocalsSignature ‘)’ 
LocalsSignature ::= Local [ ‘,’ Local ]* 
Local ::= Type [ Id ] 

같은 구문을 나열 .locals이을 지시어 II.15.4.1.3에 설명되어 있습니다 그것은 Type의 일부가 아닌 경우가 [0]을 허용하는 것 아무것도 없다 , Type[으로 시작하는 항목을 허용하지 않습니다. 내 생각에 이것은 사람의 독자가 위치 0이 지역 변수 인 CS$0$0000임을 알 수 있도록하기 위해 Microsoft의 구현과 관련된 문서화되지 않은 특이한 것으로, 생성 된 지침이 색인으로 지역 변수에 액세스 할 때 유용합니다.

ILAsm을 실험하면 이것이 정확히 의미하는 바입니다.간단한 C# 프로그램 촬영 : 다음

static class Program { 
    static void Main() { 
     int i = 0, j = 1; 
    } 
} 

을하고 컴파일하고 분해 (csc test.cs && ildasm /text test.exe >test.il)를 보여줍니다

:

.... 
.locals init (int32 V_0, 
     int32 V_1) 
IL_0000: nop 
IL_0001: ldc.i4.0 
IL_0002: stloc.0 
IL_0003: ldc.i4.1 
IL_0004: stloc.1 
IL_0005: ret 
.... 

.locals

.locals init ([0] int32 V_0, [0] int32 V_1) 

유용한 경고 메시지를 제공

에 수정
test.il(41) : warning : Local var slot 0 is in use 

실제로 다른 유형의 변수를 선언 한 다음 [2], [1], [0]을 사용하여 순서를 변경하고 결과를 즉시 분해하면 변수가 재정렬되었음을 알 수 있습니다.

+0

사양이 있지만 "[0]"을 설명하지 않은 것 같아 "!!"시도하지 않았습니다. – jrv

+0

맞아요. 시험을 치러야했습니다. – hvd

+0

[0]은 ldloc 및 stloc 명령어에서 중요한 변수가있는 로컬 슬롯을 설명합니다. ldloc 및 stloc 명령어가 올바른 변수 슬롯에로드되고 저장되는 한 [0]과 [1]은 좋지만 불필요한가요? – jrv