다음을 통해 공유


포인터 레이아웃

포인터 레이아웃은 구조체 또는 배열의 포인터를 설명합니다.

pointer_layout<>

pointer_layout<> 필드는 형식 문자 FC_PP FC_PAD, 뒤에 하나 이상의 포인터 설명, 그리고 FC_END 서식 문자로 끝나는 형식 문자로 구성됩니다(나중에 설명함):

FC_PP
FC_PAD
{ pointer_instance_layout<> }*
FC_END

pointer_instance_layout<> 필드는 포인터의 단일 또는 여러 가지의 인스턴스를 설명하는 형식 문자열입니다. 다음 필드는 다음 설명자에서 사용됩니다:

  • offset_in_memory

    메모리에서 포인터의 위치에 관한 부호 있는 오프셋입니다. 구조에 있는 포인터의 경우 이러한 오프셋은 구조의 끝(적응 구조에서 비적응 부분의 끝에서부터의 음수인 오프셋입니다. 배열의 경우 오프셋은 배열의 시작 부분부터입니다.

  • offset_in_buffer

    버퍼에서 포인터의 위치에 관한 부호 있는 오프셋입니다. 구조에 있는 포인터의 경우 이러한 오프셋은 구조의 끝(적응 구조에서 비적응 부분의 끝에서부터의 음수인 오프셋입니다. 배열의 경우 오프셋은 배열의 시작 부분부터입니다.

  • offset_to_array

    포함하는 구조에서 포인터가 처리되는 포함된 배열로의 오프셋입니다. 최상위 배열의 경우 이 필드는 항상 0입니다.

  • 반복

    동일한 레이아웃<>을 설명하고 있는 총 포인터 수입니다.

  • 증분

    반복 중에 연속 포인터 사이의 증분입니다.

  • number_of_pointers

    반복 인스턴스에서 다른 포인터 수입니다.

  • pointer_description

    포인터 설명입니다.

모든 포인터 인스턴스 레이아웃은 다음의 단일 pointer_instance<8>을 사용합니다:

offset_to_pointer_in_memory<2> 
offset_to_pointer_in_buffer<2> 
pointer_description<4>

다음은 인스턴스 설명자입니다:

단순 형식에 대한 포인터의 단일 인스턴스:

FC_NO_REPEAT FC_PAD 
pointer_instance<8>

고정 반복 포인터:

FC_FIXED_REPEAT FC_PAD 
iterations<2> 
increment<2> 
offset_to_array<2> 
number_of_pointers<2>
{ pointer_instance<8> }*

가변 반복 포인터:

FC_VARIABLE_REPEAT (FC_FIXED_OFFSET | FC_VARIABLE_OFFSET) 
increment<2> 
offset_to_array<2> 
number_of_pointers<2> 
{ pointer_instance<8> }*

고정 반복 및 가변 반복 포인터 인스턴스의 경우 반복 인스턴스의 각 포인터에 대한 오프셋 및 포인터 설명 집합이 있습니다.

포인터 레이아웃 디자인 문제

이 섹션에서는 적응 구조 및 포함된 포인터 처리와 관련된 문제를 해결합니다. 문제는 컴파일러가 일부 중복성을 포함한 구조 및 배열에 관한 포인터 레이아웃을 생성한다는 것 입니다. 이 기능은 정보가 도움을 주기 때문에 유용합니다. 예를 들어, 적응 구조는 구조의 모든 포인터 및 적응 구조에 속하는 적응 배열의 모든 포인터를 지원하기 위해 하나의 포인터 레이아웃을 탐색(walk)할 수 있습니다. 그러나 NDR 엔진이 적절한 순서로 모든 포인터 레이아웃을 처리하기 위해 추가 작업을 실행해야 하는 이를 포함하는 상황이 있으며, 각 포인터를 한 번만 처리하게 됩니다.

컴파일러에서 생성하는 내용

이 섹션에서 설명하는 모든 개체에는 포인터가 있기 때문에 예를 들어, 적응 구조에는 배열 요소뿐만 아니라 구조 부분에도 포인터가 있습니다. 요소는 포인터가 있는 단순 구조입니다.

  1. 적응 구조, 단일 수준

    적응 설명자에는 구조와 배열 모두에서 모든 포인터가 설명되는 PP 부분이 있습니다. 구성원 목록에 포인터 대신에 FC_LONG이 있습니다. CARRAY 배열 설명자에는 포인터 설명자 없이 embedded_complex를 사용하는 요소가 있습니다. 요소에는 여전히 단일 포인터 설명자가 있습니다. 포인터 레이아웃은 단순 구조 설명자 및 적응 구조의 구성원 레이아웃 앞에 옵니다.

  2. 적응 구조, 둘 이상의 수준

    PP 설명에는 모든 수준에 포인터가 있습니다. 내부 적응 구조와 동일한 배열 설명을 다시 사용합니다. 구성원 목록에 포인터 대신에 FC_LONG이 있습니다. 포함된 구조는 포함된 복합을 사용하여 제공됩니다. 적응 구조 설명자는 있는 그대로 다시 사용됩니다. 구조의 플랫 부분 크기도 완전해집니다. 즉, 최상위 구조 크기에 포함된 구조의 플랫 크기가 포함됩니다.

  3. 복합 구조, 단일 수준

    포인터 구성원은 FC_POINTER로 표시됩니다. 포인터 레이아웃이 간소화되어 목록의 각 FC_POINTER 항목에는 포인터 설명자(4바이트)가 있습니다. 포인터 레이아웃은 멤버 워크와 병렬로 진행됩니다. 즉, FC_POINTER 다음 포인터 설명이 처리됩니다. CARRAY 배열에는 배열의 모든 설명자, 그리고 포함된 복합을 사용하는 요소가 해당 순서대로 포함된 포인터 레이아웃이 있습니다. 요소 설명자가 다시 사용됩니다. 구조의 편평한 부분의 크기가 완전해집니다. 즉, 최상위 구조의 플랫 크기에는 포함된 구조의 플랫 크기가 포함됩니다. 구성원 레이아웃은 복한 구조에 대한 포인터 레이아웃 앞에 옵니다.

    따라서 적응 배열 설명 생성은 적응 구조 내부 배열인지, 복합 구조 내부 배열인지에 따라 달라집니다.

  4. 복합 구조, 2개 이상의 수준, 복합 내 복합

    최상위 복합 구조에는 해당 구성원 포인터가 있으며 포함된 복합 구조에는 해당 구성원 포인터가 있습니다. 적응 구조 설명자는 다시 사용됩니다. 맨 위의 배열 설명자는 포함된 구조에서 다시 사용된 배열입니다.

  5. 포함된 규칙 구조가 있는 복합 구조

    최상위 적응 구조에는 해당 구성원 포인터가 있습니다. 적응 구조 설명자는 있는 그대로 다시 사용됩니다. 배열 설명자는 포함된 적응 구조에서 다시 사용됩니다. 즉, 배열 설명자에 포인터가 없습니다. 요소에 해당 포인터 설명자가 있습니다.

  6. 포인터가 있는 구조의 배열

    포인터가 있는 단순 구조의 배열은 배열 크기 조정 여부에 따라서 SMFARRAY 또는 CARRAY로 생성되지만, 두 경우에서는 모두 완료된 포인터 레이아웃(FIXED_REPEAT 혹은 VARIABLE_REPEAT)을 포함하고 있습니다. 포인터 레이아웃은 구성원 레이아웃 앞에 옵니다.

    포인터가 있는 복한 구조의 배열은 고정 또는 크기 조정 여부와는 상관없이 BOGUS_ARRAY 생성되고 두 경우에는 모두 포인터 레이아웃이 없습니다.

NDR 엔진의 기능

이 섹션에서는 NDR 엔진 동작을 설명합니다.

마샬링 패스

  1. 적응 구조 및 포함된 적응 구조체입니다.

    최상위 구조는 단일 수준 구조처럼 동작합니다.

  2. 적응 배열이 있는 포함된 복합 구조

    모든 복합 구조는 외부 구조를 복합 구조로 강제로 설정하게 됩니다. 포함된 구조는 배열을 마샬링하지는 않습니다. 모든 구조는 멤버를 마샬링하기만 하면 항상 포함된 포인터를 통과하게 되며 구성원은 FC_POINTER가 됩니다.

  3. 적응 구조가 있는 복합 구조

    포함된 맨 위 적응 구조는 적응 배열과 모든 포인터 대상(pointee)을 마샬링합니다. NDR 엔진은 중첩된 적응 구조가 있는 경우라면 하위로 내려가지는 않습니다. 이 방식을 통하여 포함된 개체의 마샬링에 관한 한, 적응 구조가 리프 개체가 되기 때문에 솔루션이 간소화됩니다. 최상위 복합 구조는 배열 마샬링을 건너뜁니다.

역 마샬링, 버프 크기 조정 및 해제 패스

역 마샬링은 마샬링과는 대칭입니다. 복합 구조에서 실행하는 첫 번째 작업은 NdrComplexStructBufferSize 함수를 호출하며 버퍼에서 포인터의 위치를 찾는 것입니다. 그런 다음, 포인터 대상(pointee)을 나란히 역 마샬링하여 사용할 포인터 대상(pointee)을 올바르게 역 마샬링할 때 동일한 체계를 사용할 수 있습니다. 크기 조정된 개체와 공용 구조체를 혼동해서는 안됩니다. 메모리 이미지는 버퍼 콘텐츠는 물론이고 크기 조정된 개체와 공용 구조체에 사용해서도 안됩니다.

마샬링 및 경계 해제를 올바르게 실행하는 데 사용되는 플래그는 포인터 대상(pointee)이 정확히 한 번 탐색(walk)이 되도록 하기 위해 버프 크기 조정 및 새제와 같은 방식으로 사용되게 됩니다.

엔디안 패스

처음에 엔디안 패스가 마샬링이나 역 마샬링과 다소 비슷합니다. 복합 구조를 처리하기 위해 두 개의 패스가 필요합니다. 첫 번째 패스는 플랫 부분을 변환하여 버퍼에서 포인터 대상(pointee) 위치를 찾습니다. 그런 다음에는 두 번째 패스가 포인터 대상(pointees)위치를 변환합니다.

엔디안 패스는 모든 구조와 모든 구성원이 리프 구성원 혹은 요소가 단순 형식이 될 때까지 단계적으로 처리된다는 것이 다른 것입니다. 역 마샬링과도 차이가 있습니다. 예를 들어 역 마샬링에서는 복합 구조에 포함된 적응 구조 혹은 이와 관련해서 적응 구조의 모든 구성원을 처리하지 않아도 되는 것입니다. 또 다른 문제로는 변환이 멱등 연산이 아니기 때문에 역 마샬링 패스는 성능의 저하 없이도 일부 조각의 역 마샬링을 다시 실행할 수 있지만, 변환은 모든 단순 형식별로 한 번씩 엄격하게 실행되어야만 한다는 것입니다.

따라서 엔디언 알고리즘을 다음과 같이 요약해 볼 수 있습니다. NDR에서는 최상위 적응 구조의 개념과 이에 해당하는 경우 이를 표시해주는 플래그를 사용하게 됩니다. 플랫 부분을 변환하여 포인트 대상(pointee)의 위치를 확보하는 등 처음 탐색(walk)할 때 이 개념은 사용이 되지는 않습니다. NDR은 모든 구조 수준의 평평한 부분을 통과하여 내려오며 포인터 처리를 하지는 않습니다. 마지막으로, NDR은 최상위 수준에서 배열을 플랫 변환합니다.

두 번째로 탐색(walk)할 때 플래그는 포함된 포인터의 패스를 표시하고 적응 구조의 더 깊은 수준, 즉 맨 위 적응 구조로 진입하지 않도록 하기 위해 사용됩니다. 이러한 방식으로 플래그는 일반적인 마샬링이나 경계 해제 동작을 강제로 적용하게 됩니다. 이는 더 깊은 수준의 적응 구조로 내려가지 않도록 하기 위한 방지를 위해서입니다.

적응 배열이 있는 복합 구조에 대한 두 번째 패스는 다음과 같이 작동합니다. 복합 구조는 일반적인 방식으로 작동합니다. 즉, 더 깊은 수준은 적응 크기 혹은 해당 적응 배열을 살펴보거나 건너뛰지 않고, 배열을 건드리지 않으며 구성원을 탐색(walk)하기만 합니다.

적응 구조가 있는 복합 구조의 경우 적응 구조는 최상위 수준인지 여부와 복합 구조에 있는지 여부를 인식하고 있어야 합니다. 배열의 플랫 부분은 맨 위 적응 구조에서 처리됩니다. 두 번째 패스에서 맨 위 적응 구조는 플랫 부분을 건너뛰고 포인터 레이아웃을 통과해서 돌아옵니다. 맨 위 복합 구조는 플랫 부분을 건너뛰고 포인터 레이아웃도 건너뛰게 됩니다.

엔디안 탐색(walk)의 강력한 측면

엔디안 탐색(walk)은 일반적인 버퍼 외부 조건을 검사를 하며 상관이 없는 특성의 다른 검사도 실행합니다. 상관된 값(예: 크기 조정 인수 및 적응 크기)을 대상으로 하는 검사는 이 단계를 사용하여 실행할수 없습니다. 나중에 역 마샬링할 때 실행되게 됩니다.