Hallo Forum,
mir ist heute möglicherweise ein Bug im ARM-GCC aufgefallen.
Wenn ich zu einem struct, der ein "perfektes" Alignment aller Members
hat, das Attribut packed gebe, dann gibt mir der Compiler auch
Warnungen:
Den Testfall habe ich einerseits angehängt, er ist aber auch über
folgenden Link im Compiler-Explorer zu sehen:
https://godbolt.org/g/ghyVdT
Ich habe auch überprüft, dass die Struct-Members immer an der selben
Stelle sitzen (ob mit oder ohne packed-Attribut):
Die Warnung scheint invertiert zu sein, d.h. sie wird für die optimal
alignten statt für die misalignten Strukturelemente ausgegeben.
Ausnahme: Für 1-Byte-Elemente (char und dergleichen) wird die Warnung
(korrekterweise) nicht ausgegeben.
Für mich sieht das tatsächlich nach einem Bug aus, auch wenn er nicht
schwerwiegend ist.
Ein weiterer kleiner Bug:
Die Meldung lautet zwar
packed attribute causes inefficient alignment for '…' [-Wattributes]
Aktiviert wird sie aber nicht mit -Wattributes, sondern mit Wpacked.
Übrigens gibt Clang an genau denselben Stellen ebenfalls Warnungen aus,
nur heißen diese dort anders:
warning: packed attribute is unnecessary for '…' [-Wpacked]
Auch wenn es IMHO unsinnig ist, für jedes Element einer gepackten
Struktur, das zufälligerweise trotz des Packens richtig alignt ist, eine
Warnung auszugeben, ist sie wenigstens korrekt. Auch das [-Wpacked]
stimmt dort.
N. G. schrieb:> Wo liegt dder Fehler?
1) Schau dir an, welche Zugriffe generiert werden.
2) Schau dir an, welche .align Direktive für entsprechende Objekte
verwendet wird.
Was du vermutlich willst, ist __attribute((_packed_,__aligned__(4)))
Hallo Yalu, hallo Johann,
stimmt, die Warnung scheint invertiert zu sein. Das sieht man z.B. wenn
man eine 16bit Variable dazwischenschiebt.
Das aligned()-Attribut änder leider weder an den Warnings, noch am
generierten Code etwas (siehe dazu den godbolt.org-Link im
Eingangsposting, da kann man schnell und einfach rumspielen).
Leider gibt es im Compiler-Explorer keinen ARM-clang und ich habe auf
dem Rechner hier auch keinen zur Verfügung.
Das mit dem -Wattributes vs. -Wpacked ist aber auch interessant...
Mit freundlichen Grüßen,
N.G.
N. G. schrieb:> Das aligned()-Attribut änder leider weder an den Warnings, noch am> generierten Code etwas
Ich meine nicht den gezeigten Code, sondern die Zugriffe. Und auch mit
inkorrekter align-Direktive kann ein Objekt korrekt aligned sein.
Merke: Aus korrekt generiertem Code lässt sich nicht die Korrektheit der
Eingabe folgern.
packed impliziert üblicherweise ein Alignment von 1.
Johann L. schrieb:> N. G. schrieb:>> Das aligned()-Attribut änder leider weder an den Warnings, noch am>> generierten Code etwas>> Ich meine nicht den gezeigten Code, sondern die Zugriffe. Und auch mit> inkorrekter align-Direktive kann ein Objekt korrekt aligned sein.>> Merke: Aus korrekt generiertem Code lässt sich nicht die Korrektheit der> Eingabe folgern.>> packed impliziert üblicherweise ein Alignment von 1.
Okay, sehe ich ein. Du hast da mehr Durchblick wie ich.
Wo lese ich denn so etwas nach, wenn ich es noch nicht weiß? Mir war
ehrlich gesagt noch nicht einmal bewusst, dass es diese Direktiven gibt,
bzw. ich kannte sie nur zum alignen von großen Arrays.
Mit freundlichen Grüßen,
N.G.
Sowas steht üblicherweise im Application Binary Interface (ABI).
Die Sprachspezifikation beschreibt lediglich eine abstrakte Maschine,
die von einer konkreten Implementation umzusetzen ist. Die
Spezifikation ist dabei allgemein gehalten und macht z.B. keine Aussagen
über:
* Layout von int (und damit über die Promotion-Regeln)
* Alignment und Layout von Datentypen
* Registerverwendung
* Binärformat (ELF, aout, ...)
* Relocations, Section-Header, etc.
etc. Dies wird im ABI ausgeführt. Testfall für packed:
1
typedefstruct{inti;}__attribute((packed))S;
2
3
Ssss={1};
und übersetzt mit
1
$ arm-gcc -c obj.c -Os -save-temps
1
.global sss
2
.data
3
.type sss, %object
4
.size sss, 4
5
sss:
6
.4byte 1
hingegen:
1
$ arm-gcc -c obj.c -Os -save-temps -Dpacked=
1
.global sss
2
.data
3
.align 2
4
.type sss, %object
5
.size sss, 4
6
sss:
7
.word 1
Die gepackte Struktur unterliegt also einem weniger strikten Alignment.
Dies sieht man in der Assembler-Quelle oder man weiß es aus dem ABI. Im
erzeugten Code sieht man es u.U. nicht mehr: Wenn ein gepacktes
Konstrukt auf ein normal aligntes folgt, dann hat auch das gepackte das
größere Alignment obwohl kein explizites Alignment gefordert ist.
Wie immer lässt sich also aus der Korrektheit des erzeugten Codes nicht
auf die Korrektheit der Eingabe schließen.
Hallo Johann,
danke!
Ich lerne immer wieder Dinge über den GCC, von denen ich nicht mal
wusste, dass es sie gibt ;-)
Und an sich dachte ich immer, dass ich mich im Vergleich zum
Durchschnitt noch eher gut auskenne...
Zur Zeit befinde ich mich allerdings im Prüfungsstress, deswegen fällt
meine Antwort so kurz aus.
Mit freundlichen Grüßen,
N.G.