Warum kümmert sich Malloc() um Grenzausrichtungen?

Lesezeit: 6 Minuten

Benutzer-Avatar
Benutzer1833028

Das habe ich gehört malloc() Richtet den Speicher basierend auf dem zugewiesenen Typ aus. Zum Beispiel aus dem Buch Verstehen und Verwenden von C-Zeigern:

Der zugewiesene Speicher wird gemäß dem Datentyp des Zeigers ausgerichtet. Beispielsweise würde eine 4-Byte-Ganzzahl an einer Adressgrenze zugeordnet werden, die durch vier gleichmäßig teilbar ist.

Wenn ich folge, bedeutet dies das
int *integer=malloc(sizeof(int)); wird auf einer Adressgrenze zugewiesen, die gleichmäßig durch vier teilbar ist. Auch ohne Gießen (int *) auf malloc.

Ich arbeitete an einem Chat-Server; Ich lese von A ähnlicher Effekt mit structs.

Und ich muss fragen: Warum spielt es logischerweise eine Rolle, worauf die Adressgrenze selbst teilbar ist? Was ist falsch daran, eine Gruppe von Speicher der Melodie von zuzuweisen n*sizeof(int) Verwenden einer Ganzzahl für die Adresse 129?

Ich weiß, wie Zeigerarithmetik funktioniert *(integer+1)aber ich kann mir nicht vorstellen, wie wichtig Grenzen sind…

  • Ich kann bestätigen, das Buch sagt wörtlich wörtlich: Dynamischer Speicher wird vom Heap zugewiesen. […] Der zugewiesene Speicher wird jedoch gemäß dem Datentyp des Zeigers ausgerichtet.

    – Cnicutar

    9. Mai 2014 um 23:46 Uhr

  • Siehe hier: gamedev.net/page/resources/_/technical/general-programming/… Es geht ein wenig darauf ein, warum die Ausrichtung wichtig ist, und die Wahl der Allokatoren. Spiele nutzen die Leistung eines Computers die meiste Zeit so gut wie möglich, und daher denke ich, dass es eine gute Idee ist, sich diesen Artikel ein wenig anzusehen Aligned Allocations Sektion. Ganz am Ende zeigt es auch Benchmarks.

    – Brandon

    10. Mai 2014 um 1:47 Uhr


  • Es gibt auch CPUs, die einen Hardware-Trap ausgeben, wenn Sie versuchen, einen nicht ausgerichteten Zeiger auf ein 32-Bit-Int zu dereferenzieren (sparc, ich sehe Sie an …).

    – André Kostur

    10. Mai 2014 um 2:33 Uhr

  • Ohne zu wissen, was die Norm sagt, merkt man sofort, dass etwas an dieser Aussage nicht stimmt. Denken Sie darüber nach, wie ein Aufruf von malloc() aussieht: malloc() hat auf keinen Fall um den Typ des Zeigers zu kennen.

    – Euro Mizellen

    10. Mai 2014 um 3:22 Uhr

  • He, ja du hast Recht. Die Aussage mag für den c++-Operator “new” wahr sein, aber nicht für malloc. Malloc muss mit dem Schlimmsten rechnen.

    – Don Hatch

    10. Mai 2014 um 10:03 Uhr

Der zugewiesene Speicher wird gemäß dem Datentyp des Zeigers ausgerichtet.

Wenn du redest mallocdas ist falsch. malloc egal, was Sie mit den Daten machen und weist Speicher zu, der so ausgerichtet ist, dass er dem strengsten nativen Typ der Implementierung entspricht.

Aus der Norm:

Der zurückgegebene Zeiger, wenn die Zuordnung erfolgreich ist, ist geeignet ausgerichtet, so dass es einem Zeiger auf jede Art von Objekt mit einer grundlegenden Ausrichtungsanforderung zugewiesen werden kann und dann verwendet, um auf ein solches Objekt oder ein Array solcher Objekte im zugewiesenen Speicherplatz zuzugreifen (bis der Speicherplatz explizit freigegeben wird).

Und:

Warum spielt es logischerweise eine Rolle, worauf die Adressgrenze selbst teilbar ist?

Aufgrund der Funktionsweise der zugrunde liegenden Maschine kann der Zugriff auf nicht ausgerichtete Daten teurer (z. B. x86) oder illegal (z. B. Arm) sein. Dadurch kann die Hardware Abkürzungen nehmen, die die Leistung verbessern / die Implementierung vereinfachen.

Benutzer-Avatar
Matt Petersson

In vielen Prozessoren verursachen nicht ausgerichtete Daten eine „Falle“ oder „Ausnahme“ (dies ist eine andere Form der Ausnahme als die, die der C++-Compiler versteht. Sogar auf Prozessoren, die nicht abfangen, wenn Daten nicht ausgerichtet sind , es ist normalerweise langsamer (z. B. doppelt so langsam), wenn die Daten nicht korrekt ausgerichtet sind.Es liegt also im besten Interesse des Compilers/der Laufzeitbibliothek, sicherzustellen, dass die Dinge gut ausgerichtet sind.

Und nebenbei, malloc (normalerweise) weiß nicht, was Sie zuweisen. Stattdessen malloc richtet ALLE Daten, unabhängig von ihrer Größe, an einer geeigneten Grenze aus, die für den allgemeinen Datenzugriff “gut genug” ist – typischerweise 8 oder 16 Bytes in modernen Betriebssystem-/Prozessorkombinationen, 4 Bytes in älteren Systemen.

Das ist weil malloc weiß nicht, ob du es tust char* p = malloc(1000); oder double* p = malloc(1000);also muss davon ausgegangen werden, dass Sie speichern double oder was auch immer das Element mit den größten Ausrichtungsanforderungen ist.

Die Bedeutung der Ausrichtung ist kein Sprachproblem, sondern ein Hardwareproblem. Einige Maschinen sind nicht in der Lage, einen Datenwert zu lesen, der nicht richtig ausgerichtet ist. Andere können dies tun, tun dies jedoch weniger effizient, z. B. indem zwei Lesevorgänge erforderlich sind, um einen falsch ausgerichteten Wert zu lesen.

  • Dies ist die richtigste Antwort. Ich füge 1) hinzu, dass malloc keine Kenntnis von der Art der Daten hat, auf die der Zeiger verweist. Malloc kann nicht sagen, ob es einen Zeiger auf 2 2-Byte-Integer oder 1 4-Byte-Integer zuweist. 2) Malloc-Implementierungen verwenden häufig verriegelte Anweisungen für die Thread-Sicherheit. Diese erfordern in der Regel ausgerichtete Daten.

    – Benutzer3344003

    10. Mai 2014 um 1:26 Uhr

  • @ user3344003 Die Antworten, die Ihnen sagen, dass die Behauptung falsch ist, sind alle richtiger als diese, die Ihnen nur sagt, warum es wahr wäre, wenn es wahr wäre, was es nicht ist.

    – Benutzer207421

    11. Mai 2014 um 4:15 Uhr

  • @EJP Dein Kommentar macht keinen Sinn. Ich habe seine Hauptfrage beantwortet: “Warum ist es wichtig, worauf die Adressgrenze selbst teilbar ist?” Das heißt, warum ist die Ausrichtung wichtig. Ich habe überhaupt nichts über malloc gesagt (und die Tatsache, dass es der strengsten Ausrichtung zuordnen muss, da es nichts über den Datentyp weiß).

    – ooga

    11. Mai 2014 um 4:23 Uhr


  • Die Schlüsselpunkte sind 1) Einige Prozessoren können nicht auf nicht ausgerichtete Daten zugreifen und 2) die meisten anderen Prozessoren sind ineffizient, wenn sie dies tun. Ooga hat beides in einer prägnanten Antwort auf die Frage, warum sich malloc darum kümmert. Die Frage ist falsch, wenn sie behauptet, dass malloc dies basierend auf dem Rückgabetyp tut.

    – Benutzer3344003

    11. Mai 2014 um 17:52 Uhr

Benutzer-Avatar
MM

Das Buchzitat ist falsch; die Erinnerung zurückgegeben von malloc ist für jeden Typ garantiert richtig ausgerichtet. Auch wenn du schreibst char *ch = malloc(37);es ist immer noch für ausgerichtet int oder jede andere Art.

Sie scheinen zu fragen: “Was ist Ausrichtung?” Wenn ja, gibt es dazu schon mehrere Fragen zu SO, zB hier, oder eine gute Erklärung von IBM hier.

Es hängt von der Hardware ab. Sogar vorausgesetzt int ist 32 Bit, malloc(sizeof(int)) könnte eine Adresse zurückgeben, die durch 1, 2 oder 4 teilbar ist. Verschiedene Prozessoren handhaben den nicht ausgerichteten Zugriff unterschiedlich.

Prozessoren lesen nicht mehr direkt aus dem RAM, das ist zu langsam (es dauert Hunderte von Zyklen). Wenn sie sich also RAM schnappen, schnappen sie es sich in großen Stücken, wie 64 Bytes auf einmal. Wenn Ihre Adresse nicht ausgerichtet ist, kann die 4-Byte-Ganzzahl zwei 64-Byte-Cachezeilen überspannen, sodass Ihr Prozessor zwei Ladevorgänge ausführen und das Ergebnis korrigieren muss. Oder vielleicht haben die Ingenieure entschieden, dass es nicht notwendig ist, die Hardware zum Beheben nicht ausgerichteter Lasten zu bauen, sodass der Prozessor eine Ausnahme signalisiert: Entweder stürzt Ihr Programm ab, oder das Betriebssystem fängt die Ausnahme ab und repariert den Vorgang (Hunderte von verschwendeten Zyklen).

Das Ausrichten von Adressen bedeutet, dass Ihr Programm gut mit der Hardware zusammenspielt.

Benutzer-Avatar
ich

Weil es schneller ist; Die meisten Prozessoren Likes Daten, die ausgerichtet sind. Sogar einige Prozessoren KANN NICHT Zugriffsdaten, die nicht abgeglichen sind! (Wenn Sie versuchen, auf diese Daten zuzugreifen, kann ein Prozessorfehler auftreten.)

1351940cookie-checkWarum kümmert sich Malloc() um Grenzausrichtungen?

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

Privacy policy