2010-10-22 5 views

Répondre

6

Alignment Les exigences spécifient les offsets d'adresse pouvant être affectés à quels types. Ceci est complètement dépendant de l'implémentation, mais est généralement basé sur la taille des mots. Par exemple, certaines architectures 32 bits nécessitent que toutes les variables int démarrent sur un multiple de quatre. Sur certaines architectures, les exigences d'alignement sont absolues. Sur d'autres (par exemple x86), les ignorer ne s'accompagne que d'une pénalité de performance.

malloc est nécessaire pour renvoyer une adresse adaptée à toute exigence d'alignement. En d'autres termes, l'adresse renvoyée peut être affectée à un pointeur de n'importe quel type. De C99 §7.20.3 (fonctions de gestion de la mémoire):

Le pointeur retourné si l'allocation réussit est correctement alignée de sorte que il peut être affecté à un pointeur à tout type d'objet puis utilisé pour accéder à un tel objet ou un tableau de tels objets dans l'espace alloué (jusqu'à l'espace est explicitement désalloué).

1

Si vous avez des besoins particuliers de alignemnt de mémoire (pour le matériel particulier ou les bibliothèques), vous pouvez consulter les répartiteurs de mémoire non portables tels que _aligned_malloc() et memalign(). Ceux-ci peuvent facilement être extraits derrière une interface "portable", mais sont malheureusement non standard.

43

Supposons que vous ayez la structure.

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

Sans alignement, il serait mis en mémoire comme celui-ci (en supposant une architecture 32 bits):

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

Le problème est que sur certaines architectures CPU, l'instruction de charger un 4 octet entier de la mémoire ne fonctionne que sur les limites de mots. Donc, votre programme devrait aller chercher chaque moitié de b avec des instructions séparées.

Mais si la mémoire a été posée comme:

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

alors l'accès à b devient simple. (L'inconvénient est que plus de mémoire est nécessaire, à cause des octets de remplissage.)

Différents types de données ont des exigences d'alignement différentes. Il est courant que char soit aligné sur 1 octet, que short soit aligné sur 2 octets et que les types à 4 octets (int, float et les pointeurs sur les systèmes 32 bits) soient alignés sur 4 octets.

malloc est requis par la norme C pour renvoyer un pointeur correctement aligné pour tout type de données.

La glibc malloc sur x86-64 renvoie des pointeurs alignés sur 16 octets.

+0

très belle explication, en effet. – AnyOneElse

+0

Belle explication. – hagrawal

+0

Désolé, je ne comprends pas ce que vous entendez par "il est courant que les caractères soient alignés sur 1 octet, courts pour être alignés sur 2 octets et de 4 octets". –

1

La documentation malloc() dit:

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

Ce qui est vrai pour la plupart tout ce que vous faites en C/C++.Cependant, comme d'autres l'ont souligné, de nombreux cas particuliers existent et nécessitent un alignement spécifique. Par exemple, les processeurs Intel supportent un type de 256 bits: __m256, qui n'est certainement pas pris en compte par malloc(). De même, si vous souhaitez allouer un tampon de mémoire pour les données à paginer (similaire aux adresses renvoyées par mmap(), etc.), vous avez besoin d'un alignement potentiellement très important qui gaspillerait beaucoup de mémoire si malloc() était pour renvoyer des tampons toujours alignés à de telles limites.

Sous Linux ou d'autres systèmes Unix, je vous suggère d'utiliser la fonction posix_memalign():

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

Ceci est la fonction la plus récente que l'on veut utiliser pour ces besoins.

Questions connexes