Ich glaube, das Problem ist, dass sich Ihr Array auf dem Stapel befindet und Ihr Compiler zu alt ist, um überausgerichtete Stapelvariablen zu unterstützen. GCC 4.6 und höher haben diesen Fehler behoben .
C11 / C ++ 11 Funktioniert alignas(64) float a[4];
nur für jede Zweierpotenzausrichtung.
So auch das GNU C, __attribute__((aligned(x)))
wie Sie es verwendet haben.
(In C11 #include <stdalign.h>
für #define alignas _Alignas
: cppref ).
Bei einer sehr großen Ausrichtung an einer 4-KB-Seitengrenze möchten Sie diese möglicherweise nicht auf dem Stapel haben.
Da der Stapelzeiger beim Starten der Funktion alles sein kann, gibt es keine Möglichkeit, das Array auszurichten, ohne viel mehr zuzuweisen, als Sie benötigen, und es anzupassen. (Compiler verwenden and rsp, -4096
oder äquivalent und verwenden keines der zugewiesenen 0 bis 4088 Bytes. Eine Verzweigung, ob dieser Speicherplatz groß genug ist oder nicht, wäre möglich, wird jedoch nicht durchgeführt, da große Ausrichtungen viel größer sind als die Größe des Arrays oder anderer lokaler Elemente sind nicht der Normalfall.)
Wenn Sie das Array aus der Funktion in eine globale Variable verschieben, sollte es funktionieren. Das andere, was Sie tun können, ist, es als lokale Variable beizubehalten (was eine sehr gute Sache ist), aber machen Sie es static
. Dadurch wird verhindert, dass es auf dem Stapel gespeichert wird. Beachten Sie, dass beide Methoden nicht thread- oder rekursionssicher sind, da nur eine Kopie des Arrays vorhanden ist.
Mit diesem Code:
#include <stdio.h>
float a[4] __attribute__((aligned(0x1000))) = {1.0, 2.0, 3.0, 4.0};
int
main(void)
{
printf("%p %p %p %p\n", &a[0], &a[1], &a[2], &a[3]);
}
Ich verstehe das:
0x804c000 0x804c004 0x804c008 0x804c00c
Welches ist, was erwartet wird. Mit Ihrem Originalcode erhalte ich nur zufällige Werte wie Sie.
alignas(64)
oder was auch immer auf Objekten mit automatischem Speicher korrekt zu implementieren . Und natürlich GNU C__attribute((aligned((64)))
Es gab einen Fehler in gcc, der dazu führte, dass das ausgerichtete Attribut nicht mit Stapelvariablen funktioniert. Es scheint mit dem unten verlinkten Patch behoben zu sein. Der unten stehende Link enthält auch einige Diskussionen zu diesem Problem.
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=16660
Ich habe Ihren obigen Code mit zwei verschiedenen Versionen von gcc ausprobiert: 4.1.2 aus einer RedHat 5.7-Box, und er ist ähnlich wie bei Ihrem Problem fehlgeschlagen (die lokalen Arrays waren in keiner Weise auf 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 obige gcc-Patch zu beheben schien):
http://code.mythtv.org/trac/ticket/6535
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.
quelle
memalign()
?Aktuelle GCC (getestet mit 4.5.2-8ubuntu4) scheinen wie erwartet zu funktionieren, wenn das Array richtig ausgerichtet ist.
Ich bekomme:
quelle
Die Ausrichtung ist nicht für alle Typen wirksam. Sie sollten eine Struktur verwenden, um die Attribute in Aktion zu sehen:
Und dann lesen Sie:
Welches ist, was Sie erwartet hatten.
Edit: Gedrückt von @yzap und folgenden @Caleb Fall Kommentar, ist das ursprüngliche Problem zu GCC - Version wegen nur . Ich habe GCC 3.4.6 gegen 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 aufweisen.
Hinweis 1: Mein vorgeschlagener Code beantwortet nicht die Frage, die ich als "Ausrichten jedes Felds des Arrays" verstanden habe.
Hinweis 2: Wenn Sie ein nicht statisches a [] in main () einfügen und mit GCC 3.4.6 kompilieren, wird die Ausrichtungsanweisung des Arrays von struct unterbrochen, der Abstand zwischen den Strukturen bleibt jedoch 0x1000 ... immer noch schlecht! (Problemumgehungen finden Sie unter @zifre Antwort)
quelle