2010-10-22 7 views

risposta

6

Alignment requisiti specificano quali offset di indirizzo possono essere assegnati a quali tipi. Questo è completamente dipendente dall'implementazione, ma generalmente si basa sulla dimensione della parola. Ad esempio, alcune architetture a 32 bit richiedono che tutte le variabili int inizino su un multiplo di quattro. Su alcune architetture, i requisiti di allineamento sono assoluti. Sugli altri (ad es. X86) il fatto che vengano visualizzati come tali viene fornito con una penalità di prestazioni.

malloc è necessario per restituire un indirizzo adatto per qualsiasi requisito di allineamento. In altre parole, l'indirizzo restituito può essere assegnato a un puntatore di qualsiasi tipo. Da C99 §7.20.3 (funzioni di gestione della memoria):

Il puntatore restituito se l'allocazione riesce è opportunamente allineato in modo che può essere assegnato ad un puntatore a qualsiasi tipo di oggetto e quindi utilizzato per accedere un tale oggetto o una matrice di tali oggetti nello spazio allocato (fino a lo spazio è esplicitamente deallocato).

1

Se avete particolari esigenze alignemnt memoria (per particolari hardware o librerie), è possibile controllare ripartitori di memoria non-portatili come _aligned_malloc() e memalign(). Questi possono essere facilmente estratti dietro un'interfaccia "portatile", ma sfortunatamente non sono standard.

43

Supponiamo di avere la struttura.

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

Senza allineamento, sarebbe disposte in memoria come questo (assumendo un'architettura a 32-bit):

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

Il problema è che in alcune architetture di CPU, l'istruzione per caricare un 4 -intervallo intero dalla memoria funziona solo sui confini delle parole. Quindi il tuo programma dovrebbe recuperare ciascuna metà di b con istruzioni separate.

Ma se la memoria è stata presentata come:

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

Poi accedere al b diventa semplice. (Lo svantaggio è che è necessaria più memoria, a causa dei byte di riempimento.)

Diversi tipi di dati hanno requisiti di allineamento diversi. È comune per char essere allineato a 1 byte, short da allineare a 2 byte e tipi a 4 byte (int, float e puntatori su sistemi a 32 bit) da allineare a 4 byte.

malloc è richiesto dallo standard C per restituire un puntatore allineato correttamente per qualsiasi tipo di dati.

glibc malloc su x86-64 restituisce puntatori allineati a 16 byte.

+0

spiegazione molto bella, davvero. – AnyOneElse

+0

Bella spiegazione. – hagrawal

+0

scusate, non sottolineo cosa intendete con "è comune che char sia allineato a 1 byte, corto per essere allineato a 2 byte e tipi a 4 byte". –

1

La documentazione malloc() dice:

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

Il che è vero per la maggior parte tutto quello che fai in C/C++.Tuttavia, come sottolineato da altri, esistono molti casi speciali che richiedono un allineamento specifico. Ad esempio, i processori Intel supportano un tipo a 256 bit: __m256, che non è certamente preso in considerazione da malloc().

Allo stesso modo, se si vuole allocare un buffer di memoria per i dati che devono essere paging (simile agli indirizzi restituiti da mmap(), ecc), allora avete bisogno di un possibilmente molto grande di allineamento che avrebbe sprecato un sacco di memoria, se fosse malloc() per restituire i buffer sempre allineati a tali limiti.

Sotto altri sistemi Unix o Linux, vi suggerisco di utilizzare la funzione posix_memalign():

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

Questa è la funzione più recente che si vuole utilizzare per tali esigenze.

Problemi correlati