2010-10-22 6 views

Antwort

6

Alignment Anforderungen angeben, welche Adressen Offsets welchen Typen zugewiesen werden können. Dies ist vollständig implementierungsabhängig, basiert jedoch im Allgemeinen auf der Wortgröße. Zum Beispiel erfordern einige 32-Bit-Architekturen, dass alle int Variablen auf einem Vielfachen von vier beginnen. Auf einigen Architekturen sind die Ausrichtungsanforderungen absolut. Bei anderen (z. B. x86) wird nur eine Leistungseinbuße verhängt.

malloc wird benötigt, um eine Adresse zurückzugeben, die für alle Ausrichtungsanforderungen geeignet ist. Mit anderen Worten, die zurückgegebene Adresse kann einem Zeiger eines beliebigen Typs zugewiesen werden. Von C99 §7.20.3 (Memory Management-Funktionen):

Der Zeiger zurückgegeben, wenn die Zuordnung ausgerichtet ist, in geeigneter Weise gelingt es so, dass es auf einen Zeiger auf jeden Objekttyp zugeordnet werden kann und dann für den Zugriff auf ein solches Objekt oder ein Array von solchen Objekten in dem zugewiesenen Speicherplatz (bis der Speicherplatz explizit freigegeben ist).

1

Wenn Sie bestimmte Speicher alignemnt Bedürfnisse (für bestimmte Hardware- oder Bibliotheken) haben, können Sie überprüfen nicht tragbaren Speicher Verteilern wie _aligned_malloc() und memalign(). Diese können leicht hinter einer "portablen" Schnittstelle abstrahiert werden, sind aber leider nicht standardisiert.

43

Angenommen, Sie haben die Struktur.

0 1 2 3 4 5 6 7 
|a|a|b|b|b|b|c|d| bytes 
|  |  | words 

Das Problem ist, dass die Anweisung auf einig CPU-Architekturen, ein 4 zu laden:

struct S { 
    short a; 
    int b; 
    char c, d; 
}; 

Ohne Ausrichtung würde es wie folgt (unter der Annahme einer 32-Bit-Architektur) in einem Speicher angelegt werden, -byte Ganzzahl aus dem Speicher funktioniert nur auf Wortgrenzen. Ihr Programm müsste also jede Hälfte von b mit separaten Anweisungen holen.

Aber wenn der Speicher als angelegt wurde:

0 1 2 3 4 5 6 7 8 9 A B 
|a|a| | |b|b|b|b|c|d| | | 
|  |  |  | 

der Zugriff auf b wird einfach. (Der Nachteil ist, dass aufgrund der Füllbytes mehr Speicher benötigt wird.)

Verschiedene Datentypen haben unterschiedliche Ausrichtungsanforderungen. Es ist üblich, dass char 1-Byte-ausgerichtet, short 2-Byte-ausgerichtet ist und 4-Byte-Typen (int, float und Zeiger auf 32-Bit-Systemen) 4-Byte-ausgerichtet sind.

malloc wird vom C-Standard benötigt, um einen Zeiger zurückzugeben, der für jeden Datentyp richtig ausgerichtet ist.

glibc malloc auf x86-64 gibt 16-Byte-ausgerichtete Zeiger zurück.

+0

sehr schöne Erklärung, in der Tat. – AnyOneElse

+0

Schöne Erklärung. – hagrawal

+0

Entschuldigung, ich verstehe nicht, was Sie meinen, "es ist üblich, dass char 1-Byte-ausgerichtet ist, kurz 2-Byte-ausgerichtet und 4-Byte-Typen". –

1

Die malloc() Dokumentation sagt:

[...] the allocated memory that is suitably aligned for any kind of variable. 

die für die meisten alles, was Sie in C tun wahr/C++.Wie jedoch von anderen dargelegt, existieren viele spezielle Fälle und erfordern eine spezifische Ausrichtung. Beispielsweise unterstützen Intel-Prozessoren einen 256-Bit-Typ: __m256, der mit Sicherheit nicht von malloc() berücksichtigt wird.

Und falls Sie einen Speicherpuffer für Daten zugewiesen werden soll, die (von mmap() usw. zurück Adressen ähnlich) werden ausgelagert ist, dann müssen Sie eine möglicherweise sehr große Ausrichtung, die viel Speicher verschwenden würde, wenn malloc() war um Puffer immer an solchen Grenzen auszurichten.

unter Linux oder anderen Unix-Systemen, schlage ich vor, Sie verwenden die posix_memalign() Funktion:

int posix_memalign(void **memptr, size_t alignment, size_t size); 

Dies ist die aktuelle Funktion, die man für solche Bedürfnisse verwenden möchte.