Warum geht GCC 6 davon aus, dass Daten 16 Byte ausgerichtet sind?

8

(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 :

%Vor%

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:

  • Keine Ausrichtungshinweise oder Attribute für diese Struktur
  • Das Objekt wurde über den Standardoperator new operator
  • initialisiert
  • Hängt von der Optimierungsstufe ab:
    • PASS: -m32 -O2
    • FEHLER: -m32 -O2 -ftree-slp-vectorize
    • PASS: -m32 -O3 -fno-tree-slp-vectorize
    • FEHLER: -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 .

    
Julien Vivenot 16.02.2017, 10:43
quelle

1 Antwort

2

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.

    
TrentP 17.02.2017, 23:33
quelle

Tags und Links