2010-12-12 4 views
12

Das Übergeben von ausgerichteten Typen oder Strukturen mit ausgerichteten Typen nach Wert funktioniert bei einigen Implementierungen nicht. Dies bricht STL-Container, da einige Methoden (z. B. die Größenänderung) ihre Argumente nach Wert übernehmen.Ausgerichtete Typen und Übergabe von Argumenten nach Wert

Ich führe einige Tests mit Visual Studio 2008 aus und bin nicht ganz sicher, wann und wie der Wertübergabe-Wert fehlschlägt. Mein Hauptanliegen ist Funktion foo. Es scheint gut zu funktionieren, aber könnte es ein Ergebnis von Inlining oder einem anderen Zufall sein? Was passiert, wenn ich die Signatur in void foo (const __m128 &) ändere?

Ihre Eingabe wird sehr geschätzt. Vielen Dank.

struct A 
{ 
    __m128 x; 
    int n; 
}; 

void foo(__m128); 
void bar(A); 

void f1() 
{ 
    // won't compile 
    // std::vector<A> vec1(3); 

    // compiles, but fails at runtime when elements are accessed 
    std::vector<__m128> vec2(3); 

    // this seems to work. WHY??? 
    std::vector<__m128, some_16_byte_aligned_allocator<__m128> > vec3(3); 

    __m128 x; 
    A a; 

    // passed by value, is it OK? 
    foo(x); 

    // won't compile 
    //bar(a); 
} 

BEARBEITEN. STL schlägt selbst mit Alignator fehl, da das Problem der Weitergabe nach dem Wert bestehen bleibt.

diesen Link gefunden pass __m128 by value

+0

Was sind die Kompilierungsfehler/Warnungen, die Sie bekommen? Ich nehme an, etwas wie "formale Parameter ... wird nicht ausgerichtet"? – celion

+0

Das ist, was ich bekomme. Fehler C2719: Unnamed-Parameter: Formaler Parameter mit __declspec (align ('16 ')) wird nicht ausgerichtet – watson1180

+0

In x64 unterstützen Funktionsargumente 16-Byte-Ausrichtung, so dass dieses Problem verschwindet. Ich weiß, dass das nicht dein unmittelbares Problem löst, aber hey, es ist marginal besser als nichts. ;) – jalf

Antwort

2

ich die einzige sichere Art und Weise denken, dies im Allgemeinen zu tun mit Bezug zu passieren ist. Einige Plattformen (z. B. Xbox 360) unterstützen das Übergeben von Vektorargumenten in Registern, aber ich denke nicht, dass dies auf x86 möglich ist.

Für den Fall std::vector müssen Sie sicherstellen, dass der zugewiesene Speicher auf 16 Bytes ausgerichtet ist; Andernfalls werden Sie abstürzen, wenn Sie versuchen, die meisten Operationen mit nicht ausgerichteten Vektoren auszuführen. Wenn Sie mehrere Plattformen unterstützen, ist ein sicherer Plan die Verwendung eines typedef, z.

typedef const MyVector& MyVectorParameter; 

Sie können dann den typedef auf Plattformen ändern, die den Vektor-Wert für die Übergabe unterstützen.

+0

Ersetzen von Allocator-Hilfe mit Std :: Vektor <__m128>, aber std :: vector kompiliert immer noch nicht. – watson1180

+0

Haben Sie 'sizeof (A)' überprüft? Wenn es kein Vielfaches von 16 Byte ist, werden nachfolgende Elemente des vom Vektor zugewiesenen Array-Speichers nicht ausgerichtet, selbst wenn der Anfang des Speichers ausgerichtet ist. –

+0

Auf meiner Plattform ist die Größe von A 32 Bytes.Falsche Ausrichtung würde einen Laufzeitabsturz verursachen, aber der Vektor wird nicht kompiliert, unabhängig vom Zuordner. – watson1180

1

die oft verwendete resize() - Funktion verursacht die gesamte Ausrichtung und vielleicht können Sie versuchen, Vektor Vorlage für __m128 zu spezialisieren?

Verwandte Themen