Warum die Adresse von a[0] ist kein Vielfaches von 0x1000?
Was genau __attribute__((aligned(x))) tut? ich habe es falsch verstanden Dies Erläuterung?
Ich verwende gcc 4.1.2.
Zifre
Ich glaube, das Problem ist, dass sich Ihr Array auf dem Stapel befindet und dass Ihr Compiler zu alt ist, um überausgerichtete Stapelvariablen zu unterstützen. GCC 4.6 und höher diesen Fehler behoben.
C11/C++11 alignas(64) float a[4]; Funktioniert einfach für jede Potenz von 2 Ausrichtung.
So auch GNU C __attribute__((aligned(x))) wie du es benutzt hast.
(In C11, #include <stdalign.h> für die #define alignas _Alignas: cppref).
Aber in Ihrem Fall einer sehr großen Ausrichtung an einer 4k-Seitengrenze möchten Sie sie möglicherweise nicht auf dem Stapel haben.
Da der Stapelzeiger beim Start der Funktion beliebig sein kann, gibt es keine Möglichkeit, das Array auszurichten, ohne viel mehr als nötig zuzuordnen und anzupassen. (Compiler werden and rsp, -4096 oder gleichwertig und verwenden Sie keines der zugewiesenen 0 bis 4088 Bytes; Eine Verzweigung, ob dieser Platz groß genug ist oder nicht, wäre möglich, wird aber nicht durchgeführt, da große Ausrichtungen, die viel größer als die Größe des Arrays sind, oder andere lokale nicht der Normalfall sind.)
Wenn Sie das Array aus der Funktion in eine globale Variable verschieben, sollte es funktionieren. Die andere Sache, die Sie tun könnten, ist, es als lokale Variable zu behalten (was eine sehr gute Sache ist), aber es zu machen static. Dadurch wird verhindert, dass es auf dem Stack gespeichert wird. Beachten Sie, dass diese beiden Methoden weder Thread-sicher noch rekursionssicher sind, da es nur eine Kopie des Arrays gibt.
was erwartet wird. Mit Ihrem ursprünglichen Code erhalte ich nur zufällige Werte wie Sie.
+1 richtige Antwort. Eine alternative Lösung besteht darin, das lokale Array statisch zu machen. Die Ausrichtung auf dem Stack ist immer ein Problem und es ist am besten, es sich zur Gewohnheit zu machen, es zu vermeiden.
– Dan Olson
8. Mai 2009 um 19:47 Uhr
Oh ja, ich habe nicht daran gedacht, es statisch zu machen. Das ist eine gute Idee, da es Namenskollisionen verhindert. Ich werde meine Antwort bearbeiten.
– Zifre
8. Mai 2009 um 19:49 Uhr
Beachten Sie, dass es durch die statische Einstellung auch nicht-reentrant und nicht-threadsicher wird.
– ArchaeaSoftware
30. September 2013 um 17:59 Uhr
Auch gcc 4.6+ handhabt dies sogar auf dem Stack korrekt.
– Texthülle
26. Dezember 2015 um 14:54 Uhr
Früher war diese Antwort richtig, jetzt ist sie es nicht mehr. gcc so alt wie 4.6, vielleicht älter, weiß, wie man den Stapelzeiger ausrichtet, um C11 / C++11 korrekt zu implementieren alignas(64) oder was auch immer auf Objekten mit automatischer Speicherung. Und natürlich GNU C __attribute((aligned((64)))
– Peter Cordes
15. Januar 2019 um 5:10 Uhr
Es gab einen Fehler in gcc, der verursachte Attribut ausgerichtet, um nicht mit Stack-Variablen zu arbeiten. Es scheint mit dem unten verlinkten Patch behoben zu sein. Der Link unten enthält auch ziemlich viel Diskussion für das Problem.
Ich habe Ihren obigen Code mit zwei verschiedenen Versionen von gcc ausprobiert: 4.1.2 von einer RedHat 5.7-Box, und es ist ähnlich wie bei Ihrem Problem fehlgeschlagen (die lokalen Arrays waren in keiner Weise an 0x1000-Byte-Grenzen ausgerichtet). Ich habe dann Ihren Code mit gcc 4.4.6 auf RedHat 6.3 ausprobiert und es hat einwandfrei funktioniert (die lokalen Arrays wurden ausgerichtet). Die Myth TV-Leute hatten ein ähnliches Problem (das der gcc-Patch oben zu beheben schien):
Wie auch immer, es sieht so aus, als hätten Sie einen Fehler in gcc gefunden, der in späteren Versionen behoben zu sein scheint.
Laut dem verlinkten Fehler war gcc 4.6 die erste Version mit diesem Problem, das für alle Architekturen vollständig behoben wurde.
– Texthülle
26. Dezember 2015 um 14:53 Uhr
Abgesehen davon ist der von gcc generierte Assembler-Code zum Erstellen ausgerichteter Variablen auf dem Stapel so schrecklich und so nicht optimiert. Ist es also sinnvoll, ausgerichtete Variablen auf dem Stapel zuzuweisen, anstatt sie aufzurufen? memalign()?
– Jérôme Pouiller
17. September 2018 um 12:14 Uhr
Neuere GCC (getestet mit 4.5.2-8ubuntu4) scheinen wie erwartet zu funktionieren, wenn das Array richtig ausgerichtet ist.
Bearbeiten:
Von @yzap und nach dem Kommentar von @Caleb Case gepusht, ist das anfängliche Problem auf die GCC-Version zurückzuführen nur. Ich habe GCC 3.4.6 im Vergleich zu GCC 4.4.1 mit dem Quellcode des Anforderers überprüft:
Es ist jetzt offensichtlich, dass ältere GCC-Versionen (irgendwo vor 4.4.1) Ausrichtungspathologien zeigen.
Hinweis 1: Mein vorgeschlagener Code beantwortet nicht die Frage, die ich als “Ausrichten jedes Felds des Arrays” verstanden habe.
Anmerkung 2: Bringen Sie nicht-statische a[] innerhalb von main() und das Kompilieren mit GCC 3.4.6 unterbricht die Ausrichtungsdirektive des Arrays von Structs, behält aber einen Abstand von 0x1000 zwischen Structs bei … immer noch schlecht! (Siehe @zifre-Antwort für Problemumgehungen)
14197000cookie-checkWerden Stack-Variablen durch das GCC-__attribute__((aligned(x))) ausgerichtet?yes