Was sind die Unterschiede zwischen #pragma pack(push, n)/#pragma pack(pop) und __attribute__((__packed__, aligned(n) )) auf GCC?

Lesezeit: 3 Minuten

Was sind speziell bei GCC (d. h. beim Kompilieren beider mit GCC) die Unterschiede zwischen der Funktionsweise der folgenden beiden?

struct foo1 {
    char a;
    int b;
} __attribute__((__packed__, aligned(n) ));

und:

#pragma pack(push, n)
struct foo2 {
    char a;
    int b;
};
#pragma pack(pop)

Sie scheinen sich anders zu verhalten:

foo1 f1;
foo2 f2;

int& i1 = f1.b; // ok
int& i2 = f2.b; // cannot bind packed field 'f2.foo2::b' to 'int&'

Warum ist bei dem einen ein Fehler und bei dem anderen nicht? Sind die Speicherlayouts zumindest gleich?

Benutzeravatar von John Bollinger
John Bollinger

Sie sagen nicht, welche Version von GCC Sie verwenden, aber Sie können das entsprechende Handbuch finden online. In dieser Hinsicht sind sie jedoch alle ziemlich kompatibel, da das Verhalten von Attributen und Pragmas, sobald sie einmal definiert sind, normalerweise aus Kompatibilitätsgründen über Versionen hinweg beibehalten wird. Konkret zitiere ich aus dem Handbuch zu GCC 4.9.3, der derzeit neusten verfügbaren Version aus der GCC 4-Reihe. Insbesondere die Abschnitte auf Typattribute und weiter Strukturpackende Pragmas sind relevant.

Das GCC-Handbuch sagt von #pragma pack und Freunde:

#pragma-Direktiven, die die ändern maximal Ausrichtung von Mitglieder von Strukturen (außer Bitfeldern mit Nullbreite), Vereinigungen und Klassen, die anschließend definiert werden.

(Betonung hinzugefügt). Es sagt von __attribute__((packed)):

Dieses Attribut, das an eine Struktur- oder Vereinigungstypdefinition angehängt ist, gibt an, dass jedes Element (außer Bitfeldern mit Nullbreite) der Struktur oder Vereinigung platziert wird, um den erforderlichen Speicher zu minimieren.

Es sagt von __attribute__ ((aligned(n))):

Dieses Attribut gibt a an Minimum Ausrichtung für Variablen des angegebenen Typsgemessen in Byte.

(Betonung hinzugefügt).

Also nein, #pragma pack(n)mit oder ohne pushbedeutet im Allgemeinen nicht dasselbe wie Anhängen __attribute__((packed, aligned(n)) zum Strukturtyp. Ersteres gibt an, dass Mitglieder betroffener Strukturen ausgerichtet werden n-Byte oder feinere Grenzen. Letztere legt fest, dass Bauteile der betroffenen Struktur mit der minimal zulässigen Polsterung verpackt werden und dass die gewählte Ausrichtungsanforderung für Exemplare der Gesamtstruktur nicht geringer sein darf als n. Diese sind nicht nur nicht gleich, sie sind sich nicht einmal sehr ähnlich.

Das solltest du finden #pragma pack(1) Das Beeinflussen einer Strukturdefinition hat die gleiche Auswirkung auf das Layout von Instanzen wie das Anhängen __attribute__((packed)) zur Definition dieser Struktur. Selbst wenn sie das gleiche Ziel erreichen, sind sie es nicht gleiche Sache. Das Verhalten und die Auswirkungen beider liegen außerhalb der C++-Spezifikation, und GCC hat das Recht, sie in anderer Hinsicht anders zu behandeln.

Wenn Sie jedoch Attribute verwenden möchten, um die Ausrichtung von Strukturmitgliedern zu beeinflussen, müssen Sie zumindest einige Attribute mitgliedweise anwenden. Zum Beispiel …

struct foo1 {
    char a;
    int b __attribute__((aligned(n)));
} __attribute__((packed));

… könnte den gleichen Effekt haben wie …

#pragma pack(push, n)
struct foo2 {
    char a;
    int b;
};
#pragma pack(pop)

…, es hängt davon ab n.

  • “Sie sollten feststellen, dass #pragma pack(1) dieselbe Wirkung auf eine Strukturdefinition hat wie das Anhängen von __attribute__((packed)) an diese Definition.” : Einer kompiliert jedoch, der andere nicht in dem vom OP geposteten Beispiel.

    – Frau

    30. Oktober 2015 um 14:31 Uhr

  • @ms beide kompilieren gut für mich mit g ++ 4.4.7. Andererseits gilt das auch für sein ursprüngliches Beispiel. Ich habe meine Antwort dennoch überarbeitet, um sie in diesem Bereich etwas einzugrenzen und zu schärfen.

    – Johannes Bollinger

    30. Oktober 2015 um 14:46 Uhr

  • in der Tat, g++ 4.4.7 (und einige ältere Versionen) kompiliert diesen Codewährend g++ 4.7.3 (und höher) nicht

    – Frau

    30. Oktober 2015 um 14:51 Uhr

1432280cookie-checkWas sind die Unterschiede zwischen #pragma pack(push, n)/#pragma pack(pop) und __attribute__((__packed__, aligned(n) )) auf GCC?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy