(Tut mir leid, dass ich es nicht geschafft habe, mein Problem auf einen einfachen fehlerhaften Testfall zu reduzieren ...)
Ich hatte Probleme mit der Aktualisierung auf GCC 6.3.0, um unsere Codebasis zu erstellen (relevante Flags: -O3 -m32
).
Insbesondere wird meine Anwendung aufgrund von GCC-Optimierungen innerhalb eines struct-ctor-Aufrufs unterbrochen.
In diesem ctor verwendete GCC movaps
:
movaps
erfordert , dass der Operand 16-Byte-ausgerichtet ist. Aber zu diesem Zeitpunkt verweist %ebx
auf mein Objekt, das nicht unbedingt 16-Byte-ausgerichtet ist. Von glibc:
"Die Adresse eines von malloc oder realloc in GNU-Systemen zurückgegebenen Blocks ist immer ein Vielfaches von acht (oder sechzehn auf 64-Bit-Systemen)."
Daher der segfault (wenn er mit -O3 -m32
erstellt wurde).
Warum scheint GCC davon auszugehen, dass das zugewiesene Objekt 16-Byte-ausgerichtet ist? Versteh ich etwas falsch?
Anmerkungen:
new
operator -m32 -O2
-m32 -O2 -ftree-slp-vectorize
-m32 -O3 -fno-tree-slp-vectorize
-m32 -O3
Dieses andere Projekt scheint ähnliche Probleme zu haben: Ссылка
Ihre Untersuchung zeigt auf -fvect-cost-model=dynamic
. Untersuchung auf meiner Codebasis zeigt eher auf -ftree-slp-vectorize
.
Es ist möglich, dass der Compiler einen Grund hat anzunehmen, dass das Objekt eine Ausrichtung von ≥ 16 Byte hat. Es ist möglich, herauszufinden, was der Compiler für die Ausrichtung hält, indem Sie den Operator alignof()
in C ++ 11 verwenden. GCC hat eine Erweiterung __alignof__
, die in C und früheren C ++ - Versionen verfügbar ist.
Die Ausrichtung einer Struktur ist die höchste Ausrichtung von allem darin rekursiv. Da könnte etwas mit höherer Ausrichtung drin sein als erwartet.
Der C ++ 11-Standard garantiert zwar, dass der von new
zurückgegebene Speicher an den von der "fundamentalen Ausrichtungsanforderung" eines Objekts benötigten Wert angepasst wird, dies gilt jedoch nur für Standardtypen und daraus hergestellte Objekte. Die Verwendung von C ++ 11 alignas()
oder die Erweiterung __attribute__((aligned(x)))
GCC, um eine höhere Ausrichtung anzufordern, könnte den von new
bereitgestellten Wert überschreiten.
Eine Lösung wäre, std::aligned_alloc()
(C ++ 11 oder höher) oder posix_memalign()
(nur POSIX, aber & lt; C ++ 11) zu verwenden, um ausgerichteten Speicher zu erhalten. Dies könnte mit der Platzierungsform des new
-Operators gekoppelt werden, um das Objekt in diesem Speicher oder klassenspezifischen Operatorüberladungen von new
und delete
zu konstruieren.
Tags und Links c++ gcc memory-alignment glibc gcc6