Freigeben über


Probleme beim Packen des C-Compilers

Packungsebenen wirken sich auf das Speicherlayout von Typen für MIDL und den Microsoft C/C++-Compiler auf die gleiche Weise aus. In Microsoft-Buildumgebungen, z. B. der buildumgebung, die von VC++ oder dem Platform Software Development Kit (SDK) definiert ist, ist die Standardpaketierebene für MIDL- und C/C++-Compiler identisch. Der Standardpackgrad für die 32-Bit- und 64-Bit-Windows-Buildumgebungen ist 8.

Natürliche Ausrichtung

Bei Typen im Arbeitsspeicher entspricht die Standardausrichtung der natürlichen Ausrichtung.

  • Ein Basistyp, z. B. short, float und __int64, und ein Zeiger wird natürlich ausgerichtet, wenn seine Darstellung bei einer Adresse beginnt, die seine Größe modulo hat. Alle derzeit unterstützten Basistypen weisen Größen von 1, 2, 4 oder 8 auf. Zeiger haben eine Größe von 4 in 32-Bit-Umgebungen und 8 in 64-Bit-Umgebungen.
  • Ein zusammengesetzter Typ wird natürlich ausgerichtet, wenn jede seiner Komponenten auf natürliche Weise relativ zum Anfang des Typs ausgerichtet ist, und wenn keine unnötigen Lücken (Auffüllungen) zwischen den Komponenten vorhanden sind. Zusammengesetzte Komponenten, z. B. Felder oder Elemente, werden zu Zeiger- oder Basistypkomponenten rekursiert.

Eine einfache Regel zur Erinnerung an dieses Verhalten ist, dass die natürliche Ausrichtung eines Typs den größten Ausrichtungen seiner Komponenten entspricht.

Es besteht eine Verbindung zwischen Ausrichtung und Arbeitsspeichergröße eines Typs in Sprachen wie C oder C++ und IDL, wie durch den Operator sizeof()ausgedrückt. Die Größe ist ein Vielfaches der Ausrichtung (das minimale Vielfache, das den Typ umfasst). Dies folgt aus einer Arraydarstellung im Arbeitsspeicher.

Die natürliche Ausrichtung ist wichtig, da der Zugriff auf falsch ausgerichtete Daten auf einigen Systemen zu einer Ausnahme führen kann. Daten können für eine sichere Manipulation markiert werden, wenn sie falsch ausgerichtet sind, aber in der Regel ist dies eine Geschwindigkeitsstrafe, die auf einigen Plattformen erheblich sein kann.

Hinweis

Im Arbeitsspeicher werden Objekte von Typen mit einer natürlichen Ausrichtung von n garantiert richtig ausgerichtet, wenn sie an Adressen platziert werden, die ein Vielfaches von n sind.

 

Verpackung im Vergleich zur Ausrichtung

Wenn Sie eine Packungsebene angeben, die größer als die natürliche Ausrichtung eines Typs ist, wird die Typausrichtung nicht geändert. Wenn Sie eine Packebene angeben, die kleiner als die natürliche Ausrichtung ist, wird die Typausrichtung auf die Packebene reduziert. Daher können die gepackten Typen im Speicher an Adressen platziert werden, die ein Vielfaches der Packebene (die reduzierte Ausrichtung) sind, ohne dass es zu einer Fehlausrichtung kommen muss. Dies wirkt sich sowohl auf einfache Typen als auch auf Komponententypen aus. Bei zusammengesetzten Typen kann das interne Layout des Typs beeinträchtigt werden, da die reduzierte Ausrichtung der Komponenten die Größe der Füllung ändern kann, die für die richtige Ausrichtung der Komponenten erforderlich ist, wodurch die Größe des Typs verringert wird.

Eine einfache Regel, um sich an dieses Verhalten zu erinnern, ist, dass die neue Ausrichtung eines gepackten Typs die kleinere der Packebene und seiner natürlichen Ausrichtung ist. Die Größe des Typs ist ein Vielfaches der neuen Ausrichtung. Der sizeof() -Operator gibt die reduzierte Größe für verpackte Typen zurück.

Beispielsweise wird bei Packungsebene 2 eine Lange auf 2 ausgerichtet und kann daher an jeder geraden Adresse platziert werden, nicht nur an den Adressen, die ein Vielfaches von 4 sind, wie es bei der natürlichen Ausrichtung der Fall wäre. Eine Struktur mit einem kurzen und einem langen, bei 2 verpackt, benötigt nicht die innere Lücke zwischen dem kurzen und dem folgenden Langen, die für die natürliche Ausrichtung erforderlich war; daher ist die Struktur jetzt nicht nur auf 2 ausgerichtet, sie hat auch ihre Größe von 8 auf 6 reduziert.

Betrachten Sie als Beispiel einen zusammengesetzten Typ, der aus einem 1-Byte-Zeichen, einer ganzen Zahl von 4 Byte und einem 1-Byte-Zeichen besteht:

struct mystructtype 
{    
    char c1;  /* requires 1 byte  */
              /* 3 bytes of padding with natural alignment only */
    long l2;  /* requires 4 bytes */
    char c3;  /* requires 1 byte  */
              /* 3 bytes of padding with natural alignment only */
 } mystruct;

Diese Struktur ist natürlich auf 4 ausgerichtet und hat die natürliche Größe von 12.

Für Packebene 4 oder höher ist die Struktur mystruct auf 4 ausgerichtet und sizeof(struct mystructtype) gleich 12. Die Struktur wird falsch ausgerichtet, wenn sie sich im Arbeitsspeicher an einer Adresse befindet, die kein Vielfaches von 4 ist.

Für packungsstufe 2 ist die Struktur auf 2 ausgerichtet und ihre Größe ist 8. Die Struktur, die mit Ebene 2 gepackt ist, wird falsch ausgerichtet, wenn sie sich im Arbeitsspeicher an einer Adresse befindet, die kein Vielfaches von 2 ist.

Für Packungsebene 1 ist die Struktur auf 1 ausgerichtet und ihre Größe ist 6. Die mit Ebene 1 gepackte Struktur kann überall platziert werden, ohne einen Fehlausrichtungsfehler zu verursachen.

/Zp

/Pack