Partager via


Disposition du pointeur

La disposition du pointeur décrit les pointeurs d’une structure ou d’un tableau.

pointer_layout<>

Un champ pointer_layout<> se compose des caractères de format FC_PP FC_PAD suivis d’une ou plusieurs descriptions de pointeur, comme décrit plus loin, et se terminant par un caractère de format FC_END :

FC_PP
FC_PAD
{ pointer_instance_layout<> }*
FC_END

Un champ pointer_instance_layout<> est une chaîne de format décrivant une ou plusieurs instances de pointeurs. Les champs suivants sont utilisés dans ces descripteurs :

  • offset_in_memory

    Décalage signé vers l’emplacement du pointeur dans la mémoire. Pour un pointeur résidant dans une structure, ce décalage est un décalage négatif de la fin de la structure (fin de la partie non conforme des structures conformes) ; pour les tableaux, le décalage est du début du tableau.

  • offset_in_buffer

    Décalage signé vers l’emplacement du pointeur dans la mémoire tampon. Pour un pointeur résidant dans une structure, ce décalage est un décalage négatif de la fin de la structure (fin de la partie non conforme des structures conformes) : pour les tableaux, le décalage est du début du tableau.

  • offset_to_array

    Décalage d’une structure englobante vers le tableau incorporé dont les pointeurs sont gérés. Pour les tableaux de niveau supérieur, ce champ sera toujours égal à zéro.

  • iterations

    Nombre total de pointeurs qui ont la même disposition<> que celle décrite.

  • increment

    Incrément entre des pointeurs successifs pendant une opération REPEAT.

  • number_of_pointers

    Nombre de pointeurs différents dans une instance de répétition.

  • pointer_description

    Description du pointeur.

Toutes les dispositions d’instance de pointeur utilisent la pointer_instance<8> unique suivante :

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

Voici les descripteurs d’instance :

Instance unique d’un pointeur vers un type simple :

FC_NO_REPEAT FC_PAD 
pointer_instance<8>

Pointeur de répétition fixe :

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

Pointeur de répétition variable :

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

Pour les instances de pointeur de répétition fixe et de répétition variable, il existe un ensemble de descriptions de décalage et de pointeur pour chaque pointeur de l’instance de répétition.

Problèmes de conception de disposition des pointeurs

Cette section traite des problèmes liés au traitement des structures conformes et des pointeurs incorporés. Le problème est que le compilateur génère des dispositions de pointeur pour les structures et les tableaux avec une redondance. Cela est bénéfique, car les informations sont utiles et, par exemple, une structure conforme peut parcourir une disposition de pointeur pour gérer tous les pointeurs de la structure et du tableau conforme faisant partie de la structure conforme. Toutefois, certaines situations incorporées nécessitent que le moteur de notification d’échec de remise effectue un travail supplémentaire pour traiter toutes les dispositions de pointeur dans la séquence appropriée, en traitant chaque pointeur exactement une seule fois.

Ce que le compilateur génère

Chaque objet abordé dans cette section comporte des pointeurs. Par exemple, une structure conforme comporte des pointeurs dans la partie structure, ainsi que dans les éléments du tableau. L’élément est une structure simple avec un pointeur.

  1. Structure conforme, niveau unique

    Le descripteur conforme a une partie PP où tous les pointeurs sont décrits, à la fois à partir de la structure et du tableau. La liste des membres a FC_LONG au lieu d’un pointeur. Le descripteur de tableau CARRAY a des éléments à l’aide d’un embedded_complex et aucun descripteur de pointeur du tout. L’élément a toujours son descripteur de pointeur unique. La disposition du pointeur précède la disposition membre dans une structure conforme et des descripteurs de structure simples.

  2. Structure conforme, deux niveaux ou plus

    La description PP contient des pointeurs de tous les niveaux. Elle réutilise la même description de tableau que la structure conforme interne. La liste des membres a FC_LONG au lieu d’un pointeur. Une structure incorporée passe par l’utilisation d’un complexe incorporé. Le descripteur de structure conforme est réutilisé tel qu’il est. La taille de la partie plate de la structure est également terminée, ce qui signifie que la taille de la structure de niveau supérieur inclurait la taille plate de la structure incorporée.

  3. Structure complexe, niveau unique

    Les membres du pointeur sont marqués par FC_POINTER. La disposition du pointeur est simplifiée de sorte qu’il existe un descripteur de pointeur (4 octets) pour chaque entrée FC_POINTER dans la liste. La disposition du pointeur s’effectue en parallèle avec une procédure membre, c’est-à-dire un FC_POINTER entraîne le traitement de la description suivante du pointeur. Le tableau CARRAY a une disposition de pointeur avec tous les descripteurs du tableau, puis de l’élément, à l’aide d’un complexe incorporé. Le descripteur d’élément est réutilisé. La taille de la partie plate de la structure est terminée ; en d’autres termes, la taille plate de la structure de niveau supérieur inclut la taille plate de la structure incorporée. La disposition membre précède la disposition du pointeur pour les structures complexes.

    Par conséquent, la génération de la description du tableau conforme est différente selon qu’il s’agit d’un tableau à l’intérieur d’une structure conforme ou à l’intérieur d’une structure complexe.

  4. Structure complexe, 2 niveaux ou plus, complexe en complexe

    La structure complexe de niveau supérieur a ses pointeurs membres, la structure complexe incorporée a ses pointeurs membres. Le descripteur de la structure conforme est réutilisé. Le descripteur du tableau du haut est le tableau réutilisé de la structure incorporée.

  5. Structure complexe avec une structure conforme incorporée

    La structure conforme de niveau supérieur a ses pointeurs membres. Le descripteur de structure conforme est réutilisé tel qu’il est. Le descripteur de tableau est réutilisé à partir de la structure conforme incorporée ; en d’autres termes, il n’a aucun pointeur au niveau du descripteur de tableau. L’élément a son descripteur de pointeur.

  6. Tableaux de structures avec pointeurs

    Un tableau de structures simples avec des pointeurs est généré en tant que SMFARRAY ou CARRAY selon la taille du tableau, mais dans les deux cas, il a une disposition de pointeur terminée (FIXED_REPEAT ou VARIABLE_REPEAT). La disposition du pointeur précède la disposition du membre.

    Un tableau de structures complexes avec des pointeurs est généré en tant que BOGUS_ARRAY, qu’il soit fixe ou dimensionné, et, dans les deux cas, il n’a pas de disposition de pointeur.

Ce que fait le moteur de notification d’échec de remise

Cette section décrit le comportement du moteur de notification d’échec de remise.

Transfert de marshaling

  1. Structures conformes et structure conforme incorporée.

    La structure de niveau supérieur se comporte comme une structure de niveau unique.

  2. Structure complexe incorporée avec tableau conforme

    Toute structure complexe force la structure externe à être une structure complexe. La structure incorporée ne marshale jamais son tableau. Chaque structure passe toujours par des pointeurs incorporés en marshalant simplement les membres et un membre qui se trouve être un FC_POINTER.

  3. Structure complexe avec structure conforme

    La structure conforme la plus incorporée marshale le tableau conforme et toutes les pointes. Le moteur de notification d’échec de remise ne descend jamais jusqu’aux structures conformes imbriquées plus profondes s’il y en a ; cela simplifie la solution, car une structure conforme est un objet feuille en ce qui concerne le marshaling d’objets incorporés. La structure complexe de niveau supérieur ignore le marshaling de tableaux.

Transferts d’unmarshaling, de bufsizing et de libération

L’unmarshaling est symétrique au marshaling ; la première opération effectuée pour les structures complexes consiste à déterminer l’emplacement des pointes dans la mémoire tampon en appelant la fonction NdrComplexStructBufferSize. Il démarshale ensuite les pointes en parallèle, ce qui permet au même schéma de démarshaler correctement les pointes à utiliser. Il ne devrait pas y avoir de confusion au sujet des objets et unions dimensionnés ; l’image mémoire ne doit pas être utilisée pour les objets et unions dimensionnés, uniquement pour le contenu de la mémoire tampon.

Les indicateurs utilisés pour effectuer le marshaling et l’unmarshaling correctement sont utilisés de la même façon que dans le bufsizing et la libération pour s’assurer que les pointes sont utilisées exactement une fois.

Transfert d’endianness

Au début, le transfert d’endianness est un peu similaire au marshaling/unmarshaling ; deux transferts sont nécessaires pour traiter des structures complexes. Le premier transfert convertit la partie plate et trouve l’emplacement des pointes dans la mémoire tampon similaire à la façon dont le bufsizing effectue cette opération pour l’unmarshaling. Le second transfert convertit ensuite les pointes.

Les transferts d’endianness diffèrent de la manière suivante : chaque structure et chaque membre doit être échelonnés jusqu’à ce que le membre ou l’élément feuille soit un type simple. C’est différent de l’unmarshaling ; dans l’unmarshaling, par exemple, il n’est jamais nécessaire de traiter des structures conformes incorporées dans des structures conformes, ou tout membre de la structure conforme, d’ailleurs. Un autre problème est que la conversion n’est pas une opération idempotente. Par conséquent, le transfert d’unmarshaling pourrait restaurer par progression l’unmarshaling de certains morceaux sans risque, alors que la conversion doit être effectuée strictement une fois par type simple.

Par conséquent, l’algorithme d’endianness peut être résumé comme suit. La notification d’échec de remise a une notion de la structure conforme de niveau supérieur et un indicateur pour marquer cela, le cas échéant. Lors de la première exécution, par exemple pour convertir la partie plate et obtenir l’emplacement des pointes, cette notion n’est pas utilisée. La notification d’échec de remise descend dans les parties plates de tous les niveaux de structures et ne s’aventure jamais dans le traitement des pointeurs. Enfin, la notification d’échec de remise convertit le tableau au niveau supérieur.

Lors de la deuxième exécution, l’indicateur est utilisé pour marquer le transfert du pointeur incorporé pour éviter d’entrer des niveaux plus profonds des structures conformes, puis la structure la plus conforme. De cette façon, l’indicateur force le comportement commun de marshaling/unmarshaling, qui consiste à éviter de descendre dans des niveaux plus profonds de structures conformes.

Le deuxième transfert pour les structures complexes avec des tableaux conformes fonctionne comme suit : les structures complexes fonctionnent de la manière commune ; ce qui signifie que les niveaux plus profonds ne regardent jamais ou ignorent leur taille conforme ou leurs tableaux conformes, et exécutent simplement leurs membres sans toucher le tableau.

Pour les structures complexes avec des structures conformes, la structure conforme doit savoir si elle de niveau supérieur et si elle se trouve dans une structure complexe. La partie plate du tableau est traitée par la structure la plus conforme. Lors du deuxième transfert, la structure la plus conforme ignore la partie plate et passe par la disposition du pointeur et retourne. La structure la plus complexe ignore sa partie plate et ignore également la disposition du pointeur.

L’aspect robuste des exécutions d’endianness

L’exécution d’endianness vérifie les conditions habituelles hors de la mémoire tampon et effectue d’autres vérifications sans corrélation. Les vérifications visant des valeurs corrélées (comme l’argument de dimensionnement par rapport à la taille conforme) ne peuvent pas être effectuées à l’aide de cette étape ; elles sont effectuées ultérieurement lors de l’unmarshaling.