2014-09-15 4 views
18

, 당신은 다음과 같은 크기를 확인할 수 있습니다F # generic 구조체에 여분의 __dummy 필드가있는 이유는 무엇입니까? F # 대화를 사용

// sizeof<A> = 4 bytes 
type A (i: int) = struct end 

// sizeof<B<int>> = 8 bytes (use any type parameter) 
type B<'T> (i: int) = struct end 

여분의 크기에 대한 이유는 일반적인 경우의 정수 __dummy 필드의 존재가 될 것으로 보인다. 다시 F # 대화를 사용하면이 typeof를 사용하여 볼 수 있습니다

  • typeof<A>DeclaredFields = [|Int32 i|]
  • typeof<B<int>>__dummy 필드가 추가되었습니다 왜 이해가 안 DeclaredFields = [|Int32 i; Int32 __dummy|]

보여줍니다.

나는 그것을 추가하기위한 책임이있는 코드가 여기에있다 생각 :

let requiresExtraField = 
    let isEmptyStruct = 
     (match ilTypeDefKind with ILTypeDefKind.ValueType -> true | _ -> false) && 
     // All structs are sequential by default 
     // Structs with no instance fields get size 1, pack 0 
     tycon.AllFieldsAsList |> List.exists (fun f -> not f.IsStatic) 

    isEmptyStruct && cenv.opts.workAroundReflectionEmitBugs && not tycon.TyparsNoRange.IsEmpty 

I을 :

if requiresExtraField then 
    yield mkILInstanceField("__dummy",cenv.g.ilg.typ_int32,None,ILMemberAccess.Assembly) ] 

Line 6290requiresExtraField가 정의되어있는 곳입니다 :

https://github.com/fsharp/FSharp.Compiler.Service/blob/master/src/fsharp/ilxgen.fs

Line 6377이 보여 가정 해보자.은 구조체에 인스턴스 필드가 없음을 의미합니다. 그러나 작성된 코드는 구조체 에 있는지 여부를 테스트하는 것입니다. 인스턴스 필드는 광산을 포함한 대부분의 구조체에서 true가됩니다. 최종 테스트의 마지막 부분은 일반적인 유형 매개 변수가 있는지 여부입니다. 따라서 requiresExtraFieldtype A (일반이 아님)의 경우 false이고 type B (일반 유형의 경우)은 true입니다.

이것은 컴파일러의 버그입니까? 아니면 코드가 맞습니까? 그것이 올 바르면이 __dummy 필드의 목적은 무엇입니까? 내가 그것을 피할 수있는 방법이 있습니까?

// sizeof<AA> = 1 
type AA = struct end 

// sizeof<BB<int>> = 1 
type BB<'T> = struct end 

내가 가지고 싶은 이유 : 다른 테스트로

, 나는 내가 __dummy 필드가 더 이상 추가되었음을 보여주는, 다음과 같은 크기를 가지고, 놀랍게도 내 유일한 인스턴스 필드, 그리고 제거 참조 유형이 아닌 값 유형은 데이터 구조에 이러한 객체를 많이 전달하는 것이 아니라 많은 객체를 저장한다는 것입니다.

+0

"cenv.opts.workAroundReflectionEmitBugs"는 일부 반향 방출 버그의 해결 방법임을 제안합니다. C#이 똑같은 일을하는지 확인 했습니까? - 코드 기록을 간략하게 살펴보면 적어도 2010 년 11 월의 F # 2로 거슬러 올라갑니다.0 - 온라인 AFAIK에서 사용할 수있는 코드의 가장 오래된 버전입니다. – Asik

+1

sizeof > = 4 프로그램에서 대화식 크기가 실제로 문제입니까? – jyoung

+0

@jyoung : 오, 나는 이것이 F # Interactive의 경우에 불과하다는 것을 알지 못했습니다. 난 그냥 sizeof > 프로그램에서, 당신이 말한 것처럼, 그것을 시도하고 4, 반면에 F 인터랙티브 8 제공합니다. 그럼 내 문제는 해결, 감사합니다! Google을 사용하여 소스 파일을 찾았으므로 더 큰 그림이 무엇인지 알지 못했습니다. 해당 fsi 파일에서 끝에있는 공용'IlxAssemblyGenerator' 유형은 단일 어셈블리에 대한 증분 ILX 코드 생성기임을 나타냅니다. 내 교화를 위해서, 그게 다 뭐야? – bananasareyellow

답변

1

설명은 @jyoung이 저의 원래 게시글 아래에있는 설명에 있습니다.

마지막 줄의 requiresExtraFieldcenv.opts.workAroundReflectionEmitBugs입니다. 이 플래그는 fscopts.fs에 설정된 것으로 보입니다. 코드 줄은 다음과 같습니다

workAroundReflectionEmitBugs=tcConfig.isInteractive; // REVIEW: is this still required? 

그래서 여분의 __dummy 필드의 문제는 F # 대화에 발생합니다.

+0

'isEmptyStruct'의 논리가 거꾸로되는지 여부에 대한 질문에 대답하지 않습니다. – ildjarn

+0

@ildjarn : 네가 맞아. 그렇지 않아. 내 원칙 문제는 더미 필드의 존재로 인해 구조체의 크기 때문에 나는 대답으로 표시했다. 그 테스트는 여전히 의문의 여지가 있습니다. – bananasareyellow