다음을 통해 공유


포인터 레이아웃

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

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입니다.

  • 반복

    설명된 레이아웃과 동일한<> 총 포인터 수입니다.

  • 증가

    REPEAT 중에 연속 포인터 사이를 증분합니다.

  • 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> }*

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

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

이 섹션에서는 규칙 구조 및 포함된 포인터 처리와 관련된 문제를 해결합니다. 문제는 컴파일러가 일부 중복성을 사용하여 구조 및 배열에 대한 포인터 레이아웃을 생성한다는 것입니다. 이는 정보가 유용하기 때문에 유용합니다. 예를 들어, 규칙 구조체는 하나의 포인터 레이아웃을 따라 구조체의 모든 포인터를 서비스하고 규칙적인 배열에서 규칙 구조의 일부인 모든 포인터를 처리할 수 있습니다. 그러나 NDR 엔진이 적절한 순서로 모든 포인터 레이아웃을 처리하고 각 포인터를 정확히 한 번 처리하는 추가 작업을 수행해야 하는 일부 포함된 상황이 있습니다.

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

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

  1. 규칙 구조체, 단일 수준

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

  2. 규칙 구조, 둘 이상의 수준

    PP 설명에는 모든 수준의 포인터가 있습니다. 내부 규칙 구조와 동일한 배열 설명을 다시 사용합니다. 멤버 목록에 포인터 대신 FC_LONG 있습니다. 포함된 구조는 포함된 복합체를 사용하여 제공됩니다. 준수 구조 설명자는 as-is재사용됩니다. 구조체의 평평한 부분의 크기도 완전해지므로 최상위 구조체 크기에는 포함된 구조체의 플랫 크기가 포함됩니다.

  3. 복합 구조체, 단일 수준

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

    따라서 규격 배열 설명 생성은 규칙 구조 내부 또는 복합 구조 내의 배열인지에 따라 다릅니다.

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

    최상위 복합 구조체에는 멤버 포인터가 있으며 포함된 복합 구조에는 해당 멤버 포인터가 있습니다. 규칙적인 구조 설명자가 다시 사용됩니다. 위쪽의 배열 설명자는 포함된 구조에서 재사용된 배열입니다.

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

    최상위=수준 규칙 구조체에는 멤버 포인터가 있습니다. 준수 구조 설명자는 as-is재사용됩니다. 배열 설명자는 포함된 규칙 구조에서 재사용됩니다. 즉, 배열 설명자에 포인터가 없습니다. 요소에 포인터 설명자가 있습니다.

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

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

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

NDR 엔진의 기능

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

마샬링 패스

  1. 규칙 구조체 및 포함된 규칙 구조체입니다.

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

  2. 규격 배열을 사용하여 포함된 복합 구조체

    모든 복합 구조체는 외부 구조체를 복합 구조로 강제합니다. 포함된 구조체는 배열을 마샬링하지 않습니다. 모든 구조체는 멤버를 마샬링하기만 하면 항상 포함된 포인터를 통과하고 멤버는 FC_POINTER 됩니다.

  3. 규격 구조체를 가진 복합 구조체

    가장 포함된 규칙 구조체는 규칙 배열과 모든 점자를 마샬링합니다. NDR 엔진이 있는 경우 더 깊은 중첩된 규칙 구조로 내림차순이 되지 않습니다. 이렇게 하면 포함된 개체의 마샬링에 관한 한 규칙 구조가 리프 개체이므로 솔루션이 간소화됩니다. 최상위 복합 구조는 배열 마샬링을 건너뜁니다.

언마샬링, 버핑 및 프리링 패스

언마샬링은 마샬링에 대칭입니다. 복잡한 구조에 대해 수행하는 첫 번째 작업은 NdrComplexStructBufferSize 함수를 호출하여 버퍼에서 점자의 위치를 찾는 것입니다. 그런 다음, 점자를 병렬로 언마샬링하여 점자를 올바르게 구분 해제하는 것과 동일한 체계를 사용할 수 있습니다. 크기가 큰 개체와 공용 구조체에 대한 혼란은 없어야 합니다. 메모리 이미지는 버퍼 내용에만 크기가 큰 개체 및 공용 구조체에 사용하면 안 됩니다.

마샬링 및 경계 해제를 올바르게 수행하는 데 사용되는 플래그는 점자를 정확히 한 번 걸도록 하기 위해 버핑 및 해제와 같은 방식으로 사용됩니다.

엔디안 패스

처음에는 엔디안 패스가 마샬링/비마할링과 다소 비슷합니다. 복잡한 구조를 처리하려면 두 개의 패스가 필요합니다. 첫 번째 패스는 플랫 파트를 변환하고 버퍼에서 버퍼의 점자 위치를 찾습니다. 그런 다음 두 번째 패스는 점자를 변환합니다.

엔디언 패스는 다음과 같은 방식으로 다릅니다. 모든 구조체와 모든 멤버는 리프 멤버 또는 요소가 간단한 형식이 될 때까지 단계별로 수행해야 합니다. 이는 비마할링과 다릅니다. 예를 들어, 비마할링에서는 해당 문제에 대해 규칙 구조 또는 규칙 구조의 멤버에 포함된 규칙 구조체를 처리할 필요가 없습니다. 또 다른 문제는 변환이 멱등 연산이 아니므로 비마할링 패스는 손상 없이 일부 조각의 경계 해제를 다시 실행할 수 있지만 변환은 모든 단순 유형별로 한 번씩 엄격하게 수행되어야 한다는 것입니다.

따라서 엔디언 알고리즘을 다음과 같이 요약할 수 있습니다. NDR에는 최상위 규칙 구조의 개념과 이를 적절하게 표시하는 플래그가 있습니다. 플랫 부분을 변환하고 점자의 위치를 얻는 것과 같이 처음 걷는 경우이 개념은 사용되지 않습니다. NDR은 모든 구조 수준의 평평한 부분을 통과하고 포인터 처리에 들어가지 않습니다. 마지막으로, NDR은 최상위 수준에서 배열을 플랫 변환합니다.

두 번째로 걸을 때 플래그는 포함된 포인터의 패스를 표시하여 규칙 구조체의 더 깊은 수준, 즉 가장 규칙적인 구조체로 들어가지 않도록 하는 데 사용됩니다. 이러한 방식으로 플래그는 일반적인 마샬링/경계 해제 동작을 강제합니다. 이는 더 깊은 수준의 규칙 구조로 내림차순으로 내림차순을 방지하는 것입니다.

규격 배열을 사용하는 복합 구조체에 대한 두 번째 패스는 다음과 같이 작동합니다. 복합 구조는 일반적인 방식으로 작동합니다. 즉, 더 깊은 수준은 규칙적인 크기 또는 해당 규칙 배열을 보거나 건너뛰지 않으며 배열을 건드리지 않고 멤버를 걷기만 하면 됩니다.

규칙 구조가 있는 복잡한 구조체의 경우 규칙 구조는 최상위 수준인지 여부와 복잡한 구조에 있는지 여부를 알고 있어야 합니다. 배열의 플랫 부분은 가장 규칙적인 최상위 구조에 의해 처리됩니다. 두 번째 패스에서 가장 규칙적인 최상위 구조는 플랫 부분을 건너뛰고 포인터 레이아웃을 통과하여 반환합니다. 가장 복잡한 구조는 플랫 부분을 건너뛰고 포인터 레이아웃도 건너뜁니다.

엔디언의 강력한 측면은

엔디안 워크는 일반적인 버퍼 외부 조건을 확인하고 상호 관련되지 않은 특성에 대한 다른 검사를 수행합니다. 이 단계를 사용하여 상관 관계 값(예: 크기 조정 인수 및 적합 크기)을 대상으로 하는 검사는 수행할 수 없습니다. 이러한 작업은 나중에 경계를 해제할 때 수행됩니다.