2013-08-08 15 views
10

den folgenden Code Angenommen:reinterpret_cast auf nicht ausgerichtete Speicher

struct A 
{ 
    int a; 
    int b; 
}; 

char* buffer = receivedFromSomeWhere(); 

A a = *reinterpret_cast<A*>(buffer + 1); 

Wenn buffer + 0 auf der Größe eines int ausgerichtet sind, wird buffer + 1 am wahrscheinlichsten auf einer nicht ausgerichteten Speicher sein. Der Standardkopiekonstruktor kopiert wahrscheinlich die zwei nicht ausgerichteten int-Member a und b. Auf einer x86/x64-Architektur, außer von der Verlangsamung des Codes, wird es die Kopie Konstruktion von a in irgendeiner unangenehmen Weise beeinflussen?

Ich weiß, dass eine gute Serialisierung das unaligned Speicherproblem lösen würde (durch vielleicht eine Polsterung irgendwo um fügen hinzu, dass die A Struktur wird in den buffer ausgerichtet werden), aber in meinem Fall, ich bin nicht verantwortlich für diesen Teil.

+0

Die Tatsache, dass es nicht ausgerichtet ist, wird wahrscheinlich nicht auf dieser Architektur von Bedeutung sein. Es ist jedoch ein undefiniertes Verhalten beim Zugriff auf Speicher mit einem Zeiger auf einen anderen Typ als die Daten mit gespeichert (mit einigen Ausnahmen) (Siehe String-Aliasing) so obwohl es gut auf Ihrer Plattform/Compiler funktioniert es ist undefined Verhalten so unportable bestenfalls – jcoder

+2

Verwenden Sie einfach "memcpy". – GManNickG

+1

Ich glaube nicht, dass es sogar auf x86 verlangsamt, es sei denn, Sie überschreiten eine Cache-Zeilengrenze. –

Antwort

4

Die Kombination von C++ und der Verwendung einer x86_64-Architektur reicht nicht aus, um zu garantieren, dass nicht ausgerichtete Zugriffe unterstützt werden. Sie müssen eine zusätzliche Garantie von Ihrer spezifischen C++ - Implementierung haben, dass reinterpret_cast auf diese Weise unterstützt wird, selbst wenn die Adresse nicht ausgerichtet ist. Wenn Sie Ihren spezifischen Compiler und das Zielsystem angeben, kann Ihnen möglicherweise jemand sagen, ob er diese Operationen unterstützt.

In Ermangelung einer solchen Garantie können Sie memcpy verwenden, um Bytes aus einem nicht ausgerichteten Puffer in ein POD-Objekt (Plain Old Data) zu kopieren. Ein guter Compiler kann solche Zugriffe optimieren.

+0

Ich dachte schon über memcpy nach, aber ich wollte das reinterpret_cast Verhalten kennen. Nun, Ihre Antwort bestätigt, dass es definitiv ein undefiniertes Verhalten ist, sogar auf einer Architektur, die für ihre nicht ausgerichtete Speicherverwaltung vertraut ist. Danke für Ihre Hilfe. – Jiwan

+0

Haben Sie ein Beispiel für einen C++ - Compiler, der Code generiert, um den nicht ausgerichteten Speicherzugriff auf eine Struktur aus zwei Ganzzahlen zu identifizieren, und diesen durch eine Substitutionsoperation behandelt? Nie zuvor mit GCC, BCC oder MSVC gesehen. Also bin ich jetzt neugierig. – harper

+0

+1 für die Erwähnung von 'memcpy' über' reininterpret_cast'. Alignment-Probleme beiseite, "reinterpret_cast" verletzt strenge Aliasing-Regel (es sei denn, Sie aktivieren ein Compiler-Flag). Es ist auch erwähnenswert, dass das Umsetzen eines Rohpuffers in ein Objekt ein undefiniertes Verhalten in C++ ist (ok in C). – PoweredByRice

-1

Die x86/x64-Architektur ermöglicht einen nicht ausgerichteten Zugriff. Wie Sie bereits geschrieben haben, könnte dies Auswirkungen auf die Leistung haben. Aber da die CPU alle Operationen erlaubt, wird es keine weiteren unangenehmen Probleme geben.

Sie sollten bedenken, dass der Cache in modernen Prozessoren die Speicherzyklen reduziert. Sie werden nicht so viele SDRAM-Zyklen haben, die durch den nicht ausgerichteten Zugriff verursacht werden.

Der Kopierkonstruktor ist überhaupt nicht mit dem Problem verbunden.

+0

Die Ausrichtung in einem C-Programm ist eine Funktion der C-Implementierung, nicht der zugrundeliegenden Architektur. Typischerweise enthält eine C-Implementierung den Compiler, das Betriebssystem und die Hardware und möglicherweise andere Komponenten. Die Tatsache, dass die Hardware nicht ausgerichteten Zugriff unterstützt, bedeutet nicht, dass das Betriebssystem oder die C-Implementierung dies zulassen. –

+0

@EricPostpischil Der reinterpret_cast sagt dem Compiler genau, dass der Entwickler es besser weiß. Der Compiler akzeptiert das Ergebnis der Besetzung. Das ist keine Frage einer C-Implementierung. – harper

+1

Das Ergebnis der Besetzung ist nicht die Frage. Sobald die Adresse in einen Zeiger auf "A" umgewandelt wurde, könnte der Compiler eine normale Ladeanweisung verwenden, um sie zu laden, und das Betriebssystem hat möglicherweise den Prozessorstatus zum Melden von Ausnahmen für nicht ausgerichtete Lasten gesetzt (wenn der Zustand anders eingestellt ist). auch wenn die Hardware nicht ausgerichtete Lasten unterstützt. Dann wird das Programm fehlschlagen. Es gibt auch andere Möglichkeiten, wie dies fehlschlagen kann, selbst wenn die zugrundeliegende Hardware nicht ausgerichtete Zugriffe unterstützt. –

Verwandte Themen