2013-11-25 9 views
15

Für diese vereinfachte Testfall:Was bedeutet die Warnung "Padding-Klasse 'Tester' mit 4 Bytes"?

#include <map> 

class Tester { 
    int foo; 
    std::map<int, int> smap; 
}; 

int main() { 
    Tester test; 
    return 0; 
} 

ich die folgende Compiler-Warnung erhalten:

$ clang++ -std=c++98 -Weverything test.cc 
test.cc:5:24: warning: padding class 'Tester' with 4 bytes to align 'smap' [-Wpadded] 
    std::map<int, int> smap; 
        ^

Kann mir jemand erklären, was diese Warnmittel, und, wie ich sollte es ansprechen?

+14

Es bedeutet, dass Sie zu viele Warnungen aktiviert haben. :) –

+0

Ja, Struct Padding ist eine * Funktion *, nicht etwas, vor dem man warnen sollte. Ich nehme an, die Flagge ist da, so dass Leute, die das * genaue * Layout ihrer Strukturen im Speicher wissen müssen, explizites Padding hinzufügen und gewarnt werden können, wenn sie welche verpasst haben, aber das ist überhaupt kein normales Szenario. – hobbs

+1

@RetiredNinja Heilige Kuh Mann, Weg, um Ihren Namen vollständig darzustellen :) – bobobobo

Antwort

10

Es gibt kein wirkliches Problem hier. In C und C++ darf der Compiler Padding nach Strukturelementen einfügen, um eine bessere Ausrichtung zu ermöglichen und somit einen schnelleren Speicherzugriff zu ermöglichen. In diesem Fall scheint es so gewesen zu sein, smap auf einer 8-Byte-Ausrichtung zu platzieren. Da ein int fast sicher vier Bytes ist, sagt die Warnung Ihnen, dass vier Bytes verschwendeten Speicherplatz in der Mitte der Struktur sind.

Wenn es mehr Mitglieder der Struktur gäbe, könnte man versuchen, die Reihenfolge der Definitionen zu ändern. Zum Beispiel, wenn Ihre Tester Mitglieder haben:

struct Tester { 
    int foo; 
    std::map<int, int> smap; 
    int bar; 
}; 

dann wäre es sinnvoll, die beiden ints zu platzieren nebeneinander Ausrichtung zu optimieren und Platzverschwendung zu vermeiden. In diesem Fall haben Sie jedoch nur zwei Member, und wenn Sie sie umschalten, fügt der Compiler wahrscheinlich noch vier Byte Padding am Ende der Struktur hinzu, um die Ausrichtung von Testers zu optimieren, wenn er innerhalb eines Arrays platziert wird.

+0

Danke! Das Setzen von 'foo' nach' smap' gibt eine andere Warnung aus: 'Padding-Größe von 'Tester' mit 4 Bytes zur Alignment-Grenze, wahrscheinlich um anzuzeigen, dass diese 4 Padding-Bytes vor dem Ende der Klasse und nicht vor' eingefügt werden smap'. Ich kann die Warnung auch eliminieren, indem ich "foo" in "long" umwandle. Die einzige Frage ist: Warum bekomme ich nicht die Warnung, wenn "int foo" die einzige Variable in "Tester" ist? –

+0

@DunPeal Da Integer nur eine 4-Byte-Ausrichtung erfordern, muss am Ende der Struktur keine Auffüllung hinzugefügt werden, um sie optimal in einem Array zu platzieren. Wenn Sie versuchen, 'foo' in' short' oder 'bool' zu ändern, wird die Warnung möglicherweise wieder angezeigt (Sie könnten es auch nicht, ich bin mir nicht sicher). –

+0

Aus den Antworten auf diese Frage dachte ich, der Compiler auf meiner Plattform (LP64) ist immer bestrebt, sicherzustellen, dass jede Struktur ein Vielfaches von 64 zugeordnet ist? Ansonsten, warum Padding stören, wenn 'foo' das letzte Mitglied ist? –

4

Ich gehe davon aus, dass Sie dies auf einem 64-Bit-System kompilieren.

Auf 64-Bit-Systemen sind Zeiger 8 Bytes. Compiler richten Strukturelemente an natürliche Grenzen aus, sodass ein 8-Byte-Zeiger an einem Offset in einer Struktur beginnt, die ein Vielfaches von 8 Byte ist.

int Da nur vier Bytes, der Compiler 4 Byte "padding" eingefügt nach foo, so daß smap auf einer 8-Byte-Grenze ist.

Edit: Während smap ist kein Zeiger, sondern ein std::map, gilt die gleiche Logik. Ich bin mir nicht sicher, was die genauen Regeln für die Ausrichtung von Objekten sind, aber das Gleiche passiert.

Was ist zu tun? Nichts. Ihr Code ist vollkommen in Ordnung, der Compiler lässt Sie nur wissen, dass dies stattgefunden hat. Es gibt absolut nichts, worüber man sich Sorgen machen müsste. -Weverything bedeutet einschalten every possible warning, die wahrscheinlich für die meisten Compilations übermäßig ist.

+0

Danke! Scheint so, als ob du recht hast; Wenn ich 'foo' in' long' ändere, verschwinden die Warnungen.Von Ihnen antworte ich, dass die einzige wirksame Bedeutung dieser Warnung ist, dass 4 Bytes Speicher für jede Instanz von 'Tester' verschwendet werden. –

+0

Um auf das 'smap'-Member zuzugreifen, wäre es immer noch teurer, mit einem Halb-Zeiger-Größen-Offset (4 Bytes) als mit der vollen Zeiger-Größe (8 Bytes) zu arbeiten, weil wir von Anfang an sprechen Struktur. – bobobobo

+1

@DunPeal Es ist nicht nur, dass der Speicher _wasted_ ist, es ist auch, dass, wenn Sie diese Datenstruktur binär-serialisieren, dann unserialisieren, sagen wir auf einer 32-Bit-Maschine, Sie werden diese mysteriöse Polsterung dort haben Der Compiler wurde möglicherweise nicht bekannt. Während Sie eine 'std :: map' trotzdem nicht serialisieren würden. Wenn das ein Rudel von Primitiven wäre, die sich einer einfachen binären Serialisierung hingeben würden, hätten Sie es vielleicht getan. Der Compiler möchte, dass Sie wissen, dass 'smap' 4 Bytes weiter von dem entfernt ist, wo Sie es für richtig halten. – bobobobo

Verwandte Themen