Neues Problem platzieren

8

In diesem Ich brauche C ++ Array-Klasse Vorlage, die eine feste Größe ist, stack-basiert und erfordert keine Standardkonstruktor Antwort Ich postete ein Stück Code, der die Platzierung neu mit Char-Array verwendet . Für mich ist das etwas absolut Normales. Aber nach den Kommentaren ist dieser Code falsch.

Kann jemand das genauer erklären?

Insbesondere was mit dem Array schief gehen kann. Was ich aus den Kommentaren verstehe, ist, dass T x[size]; möglicherweise nicht in char x[size*sizeof(T)]; passt. Ich glaube nicht, dass das wahr ist.

BEARBEITEN:

Ich bin nur mehr und mehr verwirrt. Ich weiß, welche Ausrichtung bei Strukturen ist. Ja, wenn Sie eine Struktur haben, beginnen die Attribute mit verschiedenen Offsets, was Sie vielleicht denken.

OK, jetzt sind wir wieder bei Arrays. Sie sagen mir, dass T x[size]; die gleiche Größe wie char x[size*sizeof(T)]; hat, aber ich kann nicht auf das char-Array als T-Array zugreifen, da es eine gewisse Ausrichtung geben könnte. Wie kann es eine Ausrichtung geben, wenn die Arrays die gleiche Größe haben?

EDIT 2:

OK, ich bekomme es endlich, es kann an einer falschen Adresse beginnen.

EDIT 3:

Thx jeder, du kannst aufhören zu posten :-) Puh, diese Summe hat mich umgehauen. Ich habe nie realisiert, dass das möglich ist.

    
Let_Me_Be 06.10.2010, 16:13
quelle

5 Antworten

13

Ein T x[size] -Array passt immer genau in size * sizeof(T) bytes, was bedeutet, dass char buffer[size*sizeof(T)] immer genau genug ist, um ein solches Array zu speichern.

Das Problem in dieser Antwort, so wie ich es verstanden habe, war, dass Ihr char -Array nicht garantiert richtig ausgerichtet ist, um das Objekt vom Typ T zu speichern. Nur malloc -ed / new -ed-Puffer sind garantiert korrekt ausgerichtet, um alle Standarddatentypen kleinerer oder gleicher Größe (oder Datentypen, die aus Standarddatentypen bestehen) zu speichern, aber wenn Sie explizit ein% co_de deklarieren % array (als lokales Objekt oder Mitgliedsteilobjekt) gibt es keine solche Garantie.

Alignment bedeutet, dass es auf irgendeiner Plattform streng (oder nicht so streng) erforderlich ist, alle char -Objekte beispielsweise auf einer 4-Byte-Grenze zuzuweisen. Z.B. Sie können ein Objekt int an der Adresse int oder 0x1000 platzieren, aber Sie können kein Objekt 0x1004 an der Adresse int platzieren. Oder, genauer gesagt, Sie können das tun, aber alle Versuche, auf diesen Speicherort als Objekt vom Typ 0x1001 zuzugreifen, führen zu einem Absturz.

Wenn Sie ein beliebiges Array int erstellen, weiß der Compiler nicht, wofür Sie es verwenden möchten. Es kann entscheiden, dieses Array an der Adresse char zu platzieren. Aus dem obigen Grund wird ein naive Versuch, ein 0x1001 -Array in einem solchen nicht ausgerichteten Puffer zu erstellen, fehlschlagen.

Die Ausrichtungsanforderungen für einige Plattformen sind streng, was bedeutet, dass alle Versuche, mit falsch ausgerichteten Daten zu arbeiten, zu Laufzeitfehlern führen. Auf einigen anderen Plattformen sind sie weniger streng: Der Code wird funktionieren, aber die Leistung wird darunter leiden.

Die Notwendigkeit für die richtige Ausrichtung bedeutet manchmal, dass Sie, wenn Sie ein int -Array in einem beliebigen int -Array erstellen wollen, den -Schnitt am Anfang eines char -Arrays haben müssen vorwärts vom Anfang des int -Arrays. Wenn sich beispielsweise das Array char bei char befindet, haben Sie keine andere Wahl als das Array 0x1001 vor Ort aus der Adresse int zu starten (das ist das Element 0x1004 mit dem Index 3 ). Um den Endteil des verschobenen char -Arrays unterzubringen, müsste das int -Array 3 Bytes größer sein als das, was der char auswertet. Aus diesem Grund ist die Originalgröße möglicherweise nicht ausreichend.

Wenn Ihr size * sizeof(T) -Array in keiner Weise ausgerichtet ist, benötigen Sie im Allgemeinen ein Array von char bytes, um ein ausgerichtetes (dh möglicherweise verschobenes) Array von Objekten vom Typ size * sizeof(T) + A - 1 unterzubringen, die ausgerichtet werden müssen bei A-Byte-Grenze.

    
AnT 06.10.2010, 16:22
quelle
0

T kann anders ausgerichtet sein als ein char.

auch, itanium abi (zum Beispiel) gibt Cookies für Nicht-pod-Array an, so dass es weiß, wie viele Elemente beim Löschen durchlaufen werden müssen (um die Destruktoren aufzurufen). Die Zuweisung über neue ist wie folgt (Iirc):

%Vor%

, so dass die Zuordnung für ein 16 Byte ausgerichtetes Objekt lautet:

%Vor%

char kann auf einigen Systemen auf 1 ausgerichtet werden, also ... sehen Sie, wo die Fehlausrichtung und Größenprobleme passen. Built-in-Typen brauchen ihre dtors nicht aufgerufen, sondern alles andere.

    
justin 06.10.2010 16:22
quelle
0

char x[size*sizeof(T)]; berücksichtigt möglicherweise Ausrichtung nicht, wobei T x [Größe]; werden. alignment (2) kann auch sehr wichtig sein, wenn Sie mit SSE-Typen arbeiten, die eine 16-Byte-Ausrichtung erfordern

    
Necrolis 06.10.2010 16:31
quelle
0

Bei einigen Systemen muss der Speicherzugriff "ausgerichtet" sein. Der Einfachheit halber bedeutet dies, dass die Adresse ein Vielfaches einer ganzen Zahl sein muss, die "Alignemnt-Anforderung" des Typs genannt wird (siehe 3.9 / 5 des C ++ - Standards).

Nehmen wir zum Beispiel an, sizeof(int) == 4 :

%Vor%

Die Adresse von charptr ist kein Vielfaches von 4. Wenn also int eine Ausrichtungsanforderung von 4 auf Ihrer Plattform hat, hat das Programm ein undefiniertes Verhalten.

Ähnlich:

%Vor%

Die Adresse von ra ist nicht garantiert ein Vielfaches von 4.

Das ist aber OK:

%Vor%

weil new garantiert, dass char-Array-Zuordnungen für jeden Typ ausgerichtet sind, der klein genug ist, um in die Zuweisung (5.3.4 / 10) zu passen.

Wenn Sie sich von automatischen Systemen entfernen, können Sie leicht erkennen, warum der Compiler keine Datenelemente ausrichtet. Überlegen Sie:

%Vor%

Wenn der Standard garantiert, dass second 4-ausgerichtet ist (immer noch vorausgesetzt, dass int 4-ausgerichtet ist), dann müsste die Größe dieser Struktur mindestens 16 sein (und ihre Ausrichtung Anforderung mindestens 4) . Da der Standard tatsächlich geschrieben wird, darf ein Compiler diese Strukturgröße 12 ohne Auffüllung und keine Ausrichtungsanforderung erhalten.

    
Steve Jessop 06.10.2010 16:29
quelle
0

§5.3.4 / 10:

  

Ein neuer Ausdruck übergibt den Betrag von   Speicherplatz für die Zuweisung angefordert   Funktion als erstes Argument des Typs   %Code%. Dieses Argument soll sein   nicht weniger als die Größe des Objekts   erschaffen werden; es kann größer sein als   die Größe des Objekts, das erstellt wird   nur wenn das Objekt ein Array ist. Zum   Arrays von Char und unsigned char, die   Unterschied zwischen dem Ergebnis der   new-expression und die Adresse   zurückgegeben von der Zuordnungsfunktion   soll ein ganzzahliges Vielfaches von sein   strengste Ausrichtung Anforderung   (3.9) eines beliebigen Objekttyps, dessen Größe ist   nicht größer als die Größe des Arrays   erstellt werden.

Dies ermöglicht die Verwendung von char-Arrays, die mit new für die Platzierungskonstruktion von geeignet große Objekte anderer Arten. Der vorab zugewiesene Puffer muss auf dem Heap zugewiesen werden. Sonst könnte es zu Alignment Problemen kommen.

    
user405725 06.10.2010 16:26
quelle

Tags und Links