Gibt es eine Garantie für die Ausrichtung der Adressrückgabe durch die neue Operation von C++?

Lesezeit: 6 Minuten

Gibt es eine Garantie fur die Ausrichtung der Adressruckgabe durch
Fang Pen Lin

Die meisten erfahrenen Programmierer wissen, dass die Datenausrichtung wichtig für die Leistung des Programms ist. Ich habe einige Programmierer gesehen, die ein Programm geschrieben haben, das eine größere Puffergröße zuweist, als sie benötigen, und den ausgerichteten Zeiger als Anfang verwendet. Ich frage mich, ob ich das in meinem Programm tun sollte, ich habe keine Ahnung, ob es eine Garantie für die Ausrichtung der Adresse gibt, die von der neuen Operation von C++ zurückgegeben wird. Also habe ich ein kleines Programm zum Testen geschrieben

for(size_t i = 0; i < 100; ++i) {
    char *p = new char[123];
    if(reinterpret_cast<size_t>(p) % 4) {
        cout << "*";
        system("pause");
    }
    cout << reinterpret_cast<void *>(p) << endl;
}
for(size_t i = 0; i < 100; ++i) {
    short *p = new short[123];
    if(reinterpret_cast<size_t>(p) % 4) {
        cout << "*";
        system("pause");
    }
    cout << reinterpret_cast<void *>(p) << endl;
}
for(size_t i = 0; i < 100; ++i) {
    float *p = new float[123];
    if(reinterpret_cast<size_t>(p) % 4) {
        cout << "*";
        system("pause");
    }
    cout << reinterpret_cast<void *>(p) << endl;
}
system("pause");

Der Compiler, den ich verwende, ist Visual C++ Express 2008. Es scheint, dass alle Adressen, die die neue Operation zurückgibt, ausgerichtet sind. Aber ich bin mir nicht sicher. Daher meine Frage: Gibt es eine Garantie? Wenn sie Garantie haben, muss ich mich nicht ausrichten, wenn nicht, muss ich.

Gibt es eine Garantie fur die Ausrichtung der Adressruckgabe durch
Richard Korden

Die Ausrichtung hat die folgende Garantie aus dem Standard (3.7.3.1/2):

Der zurückgegebene Zeiger muss geeignet ausgerichtet sein, damit er in einen Zeiger eines beliebigen vollständigen Objekttyps konvertiert und dann für den Zugriff auf das Objekt oder Array im zugewiesenen Speicher verwendet werden kann (bis der Speicher explizit durch einen Aufruf einer entsprechenden Freigabefunktion freigegeben wird). .

BEARBEITEN: Danke an Timday für das Hervorheben von a Insekt in gcc/glibc, wo die Garantie nicht gilt.

BEARBEITEN 2: Bens Kommentar hebt einen interessanten Randfall hervor. Die Anforderungen an die Zuordnungsroutinen gelten nur für die vom Standard bereitgestellten. Wenn die Anwendung eine eigene Version hat, gibt es keine solche Garantie für das Ergebnis.

  • In der Theorie. Wenn Sie in der Praxis gcc+glibc und SSE-Typen auf einem 32-Bit-System verwenden, sollten Sie Folgendes beachten gcc.gnu.org/bugzilla/show_bug.cgi?id=15795 .

    – uhrtag

    3. Februar 09 um 11:44 Uhr

  • @BenVoigt: Hast du mehr Details? Wollen Sie damit sagen, dass es eine Garantie gibt, diese aber anderswo gegeben ist? Der Entwurf, den ich habe (N3337), diskutiert unter 5.3.4/10 Anforderungen für die Rückgabe von (unsigned) char-Arrays und hat einen Kommentar, der beginnt: „Weil Zuordnungsfunktionen angenommen werden, dass sie Zeiger auf Speicher zurückgeben, der für Objekte von angemessen ausgerichtet ist jeder Typ mit fundamentaler Ausrichtung…”.

    – Richard Corden

    17. Dezember 2012 um 12:49 Uhr

  • @RichardCorden: Der von der Zuordnungsfunktion zurückgegebene Zeiger operator new[]() ist gut ausgerichtet. Aber new T[n] nicht erforderlich ist und normalerweise nicht zurückkehrt operator new[](n * sizeof (T)). Fast jeder Compiler fügt Metadaten voran, um die Anzahl der Elemente zu verfolgen (damit die richtige Anzahl an Destruktoren aufgerufen wird), und das Einfügen eines Headers davor ändert offensichtlich die Ausrichtung.

    – Ben Voigt

    17. Dezember 2012 um 16:04 Uhr

  • @BenVoigt: IMHO hebt das Hinzufügen von 5.3.4/10 die Bemühungen des Komitees hervor, in allen (Rechts-)Fällen ausdrücklich eine korrekte Ausrichtung zu garantieren. Der Compiler kann leicht Metadaten am Anfang eines Arrays hinzufügen und eine Lücke hinterlassen. Beim weiteren Lesen hat 5.3.4/5: the new-expression yields a pointer to the initial element (if any) of the array. So new[] gibt das Element des Arrays zurück – nicht nur einen Speicherplatz. Es muss also die richtige Ausrichtung usw. haben.

    – Richard Corden

    17. Dezember 2012 um 17:25 Uhr

  • @Richard: Die andere Sache ist die minimal korrekte Ausrichtung, die Sie erhalten new[] ist nicht dasselbe wie eine optimale Ausrichtung. Aus Performance-Gründen möchten Sie bestimmte Strukturen am Cache ausrichten. Selbst wenn Sie Ihre Antwort aktualisieren, um den richtigen Abschnitt des Standards zu zitieren, wird die gestellte Frage daher immer noch nicht beantwortet. Auch einige Anweisungen (insbesondere SSE) erfordern strengere Ausrichtung.

    – Ben Voigt

    17. Dezember 2012 um 18:04 Uhr


Dies ist eine späte Antwort, aber nur um die Situation unter Linux zu verdeutlichen – auf 64-Bit-Systemen ist der Speicher immer auf 16 Byte ausgerichtet:

http://www.gnu.org/software/libc/manual/html_node/Aligned-Memory-Blocks.html

Die Adresse eines Blocks, die von malloc oder realloc im GNU-System zurückgegeben wird, ist immer ein Vielfaches von acht (oder sechzehn auf 64-Bit-Systemen).

Der new Betreiber ruft malloc intern (vgl ./gcc/libstdc++-v3/libsupc++/new_op.cc), also gilt dies für new sowie.

Die Implementierung von malloc was Teil der ist glibc grundsätzlich definiert
MALLOC_ALIGNMENT sein 2*sizeof(size_t) und size_t ist 32 Bit = 4 Byte und 64 Bit = 8 Byte auf einem x86-32- bzw. x86-64-System.

$ cat ./glibc-2.14/malloc/malloc.c:
...
#ifndef INTERNAL_SIZE_T
#define INTERNAL_SIZE_T size_t
#endif
...
#define SIZE_SZ                (sizeof(INTERNAL_SIZE_T))
...
#ifndef MALLOC_ALIGNMENT
#define MALLOC_ALIGNMENT       (2 * SIZE_SZ)
#endif

C++17 ändert die Anforderungen an die new allocator, so dass es erforderlich ist, einen Zeiger zurückzugeben, dessen Ausrichtung gleich dem Makro ist __STDCPP_DEFAULT_NEW_ALIGNMENT__ (was durch die Implementierung definiert wird, nicht durch Einfügen eines Headers).

Dies ist wichtig, weil diese Größe sein kann größer als alignof(std::max_align_t). In Visual C++ ist die maximale reguläre Ausrichtung beispielsweise 8 Byte, aber die Standardeinstellung new gibt immer 16 Byte ausgerichteten Speicher zurück.

Beachten Sie auch, dass, wenn Sie die Standardeinstellung überschreiben new mit Ihrem eigenen Allokator sind Sie es erforderlich sich an die halten __STDCPP_DEFAULT_NEW_ALIGNMENT__ sowie.

  • Ich meine, Sie können die Überladung immer dort aufrufen, wo Sie die Ausrichtung explizit angeben. new tut dies automatisch, wenn der Typ eine neu-erweiterte Ausrichtung hat.

    – Kristian S

    12. August 19 um 14:08 Uhr

  • “Beachten Sie auch, dass Sie sich an die halten müssen, wenn Sie den Standardwert new mit Ihrem eigenen Allocator überschreiben STDCPP_DEFAULT_NEW_ALIGNMENT auch.” Was ist die Quelle dafür?

    – kula85

    20. Januar 21 um 20:04 Uhr

Übrigens die MS-Dokumentation erwähnt etwas über malloc/new-Rückgabeadressen, die 16-Byte-ausgerichtet sind, aber aus Experimenten ist dies nicht der Fall. Ich brauchte zufällig das 16-Byte-Alignment für ein Projekt (um Speicherkopien mit erweitertem Befehlssatz zu beschleunigen), am Ende habe ich darauf zurückgegriffen, meinen eigenen Allocator zu schreiben …

Die Plattform ist neu/neu[] -Operator gibt Zeiger mit ausreichender Ausrichtung zurück, sodass er mit grundlegenden Datentypen (double,float usw.) gut funktioniert. Zumindest jeder vernünftige C++-Compiler+Runtime sollte das tun.

Wenn Sie spezielle Ausrichtungsanforderungen wie für SSE haben, ist es wahrscheinlich eine gute Idee, spezielle aligned_malloc-Funktionen zu verwenden oder Ihre eigenen zu erstellen.

1644152467 312 Gibt es eine Garantie fur die Ausrichtung der Adressruckgabe durch
Anthony Lambert

Ich habe an einem System gearbeitet, bei dem sie die Ausrichtung verwendet haben, um das ungerade Bit für den eigenen Gebrauch freizugeben!

Sie verwendeten das ungerade Bit, um ein virtuelles Speichersystem zu implementieren.

Wenn bei einem Zeiger das ungerade Bit gesetzt war, wurde dies verwendet, um anzuzeigen, dass er (abzüglich des ungeraden Bits) auf die Informationen zeigte, um die Daten aus der Datenbank zu erhalten, nicht auf die Daten selbst.

Ich hielt dies für ein besonders hässliches Stück Codierung, das für sein eigenes Wohl viel zu schlau war !!

Toni

.

797300cookie-checkGibt es eine Garantie für die Ausrichtung der Adressrückgabe durch die neue Operation von C++?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy