mallopt - Définir les paramètres d'allocation de
mémoire
Bibliothèque C standard (libc, -lc)
#include <malloc.h>
int mallopt(int param, int value);
La fonction mallopt() ajuste les paramètres qui
contrôlent le comportement des fonctions liées à
l'allocation de mémoire (voir malloc(3)). Le paramètre
param indique le paramètre à modifier, et value
indique la nouvelle valeur pour ce paramètre.
Les valeurs suivantes peuvent être assignées
à param :
- M_ARENA_MAX
- Si ce paramètre à une valeur non nulle, il définit
une limite dure sur le nombre maximal d'arènes qui peuvent
être créées. Une arène représente une
réserve de mémoire qui peut être utilisée par
des appels à malloc(3) (et fonctions similaires) pour
répondre à des requêtes d'allocation. Les
arènes sont sécurisées vis-à-vis des fils
d'exécution et peuvent répondre à de multiples
requêtes concurrentes. Un compromis est à trouver entre le
nombre de fils d'exécution et le nombre d'arènes. Plus il y
a d'arènes et plus la compétition par fil d'exécution
est basse au détriment d'une consommation mémoire plus
élevée.
- La valeur par défaut de ce paramètre est 0, ce qui
signifie que la limite du nombre d'arènes est
déterminée conformément à la valeur de
M_ARENA_TEST.
- Ce paramètre est disponible depuis la glibc 2.10 à
l’aide de --enable-experimental-malloc, et par défaut
depuis la glibc 2.15. Dans certaines versions de
l’allocateur il n'y avait pas de limite sur le nombre
d'arènes créées (sur CentOS 5 et RHEL 5
par exemple).
- Lors de l'utilisation de versions plus récentes de la glibc, les
applications peuvent dans certains cas faire preuve d’une grande
compétition lors de l'accès aux arènes. Dans ces cas,
il peut être bénéfique d'augmenter M_ARENA_MAX
pour la faire correspondre au nombre de fils d'exécution. Il s'agit
d'un comportement similaire aux stratégies appliquées par
tcmalloc et jemalloc (à des réserves d'allocation par fil
d'exécution par exemple).
- M_ARENA_TEST
- Ce paramètre définit, en nombre d'arènes
créées, la valeur pour laquelle la configuration du
système sera examinée afin de déterminer une limite
dure sur le nombre d'arènes créées. Consultez
M_ARENA_MAX pour la définition d'une arène.
- Le calcul de la limite dure du nombre d'arènes est définit
par l'implémentation et est généralement un multiple
du nombre de CPU disponibles. Le résultat est définitif une
fois la limite dure calculée, et il contraint le nombre total
d'arènes.
- La valeur par défaut du paramètre M_ARENA_TEST
est 2 sur les systèmes où sizeof(long)
vaut 4 ; autrement, la valeur par défaut
est 8.
- Ce paramètre est disponible depuis la glibc 2.10 à
l’aide de --enable-experimental-malloc, et par défaut
depuis la glibc 2.15.
- La valeur de M_ARENA_TEST n'est pas utilisée lorsque
M_ARENA_MAX a une valeur non nulle.
- M_CHECK_ACTION
- Ce paramètre contrôle le comportement de la glibc lorsque
des erreurs de programmation sont détectées (par exemple,
lors qu'un pointeur est libéré plusieurs fois). Les
3 bits de poids faible (bits 2, 1 et 0) de cette valeur ont les
significations suivantes :
- Bit 0
- Lorsque ce bit est positionné, un message d'une ligne
détaillant l'erreur est affiché sur stderr. Le
message commence par la chaîne "*** glibc
detected ***", suivi par le nom du programme, le nom de la
fonction de l'allocation mémoire qui a détecté
l'erreur, une brève description de l'erreur, puis l'adresse
mémoire où l'erreur a été
détectée.
- Bit 1
- Lorsque ce bit est positionné, après avoir affiché un
message d'erreur configuré par le bit 0, le programme est
terminé en appelant abort(3). Depuis la glibc 2.4, si
le bit 0 est également positionné, alors le programme
affiche également — entre l'affichage d'un message
d'erreur et l'abandon du programme — l'état de la
pile à la manière de backtrace(3) et les projections
en mémoire du processus à la manière de
/proc/pid/maps (voir proc(5)).
- Bit 2 (depuis la
glibc 2.4)
- Ce bit a un effet uniquement si le bit 0 est également
positionné. Lorsqu'il est positionné, alors le message
d'erreur d'une ligne décrivant l'erreur est simplifié et
contient uniquement le nom de la fonction où l'erreur a
été détectée ainsi qu'une brève
description de l'erreur.
- Les autres bits de value sont ignorés.
- La combinaison des bits décrits ci-dessus permet de configurer
M_CHECK_ACTION avec les valeurs suivantes :
- 0
- Ignorer les erreurs et continuer l'exécution (sans résultats
définis).
- 1
- Afficher un message d'erreur détaillé et continuer
l'exécution.
- 2
- Interrompre le programme.
- 3
- Afficher un message d'erreur détaillé, l'état de la
pile et des projections en mémoire, puis interrompre le
programme.
- 5
- Afficher un message d'erreur simple et continuer l'exécution.
- 7
- Afficher un message d'erreur simple, l'état de la pile et des
projections en mémoire, puis interrompre le programme.
- Depuis la glibc 2.3.4, M_CHECK_ACTION a pour valeur par
défaut 3. Dans la glibc 2.3.3 et antérieures, la
valeur par défaut est 1).
- Il est recommandé d'utiliser une valeur M_CHECK_ACTION non
nulle, car sinon l'arrêt impromptu du programme risque
d'être différé, ce qui rend très difficile de
retrouver l'origine du problème.
- M_MMAP_MAX
- Ce paramètre indique le nombre maximal de requêtes
d'allocation qui peuvent être servies simultanément avec
mmap(2). Il permet de préserver les performances de certains
systèmes qui ont un nombre limité de tables internes
à disposition de mmap(2).
- La valeur par défaut est 65 536, valeur qui n'a pas de sens
particulier mais sert seulement de protection. Configurer ce
paramètre à 0 désactive l'utilisation de
mmap(2) pour servir de grandes requêtes d'allocation.
- M_MMAP_THRESHOLD
- Lorsqu'une requête d'allocation supérieure ou égale
au seuil M_MMAP_THRESHOLD (en octets) ne peut être
satisfaite depuis la liste de blocs libres, les fonctions d'allocation de
mémoire utilisent mmap(2) plutôt que d'augmenter la
taille du segment de données avec sbrk(2).
- Allouer de la mémoire avec mmap(2) permet toujours aux blocs
de mémoire alloués d'être rendus de manière
indépendante au système. Cela représente un avantage
significatif comparé au tas qui ne peut être
désalloué que si la mémoire est libérée
par le haut. D'autre part, il y a certains inconvénients à
utiliser mmap(2) : l'espace désalloué n'est
pas considéré comme libéré, l'empêchant
d'être réutilisé pour de futures allocations ;
de la mémoire peut être gaspillée car les allocations
à l’aide de mmap(2) doivent être
alignées sur une taille de page ; et le noyau doit effectuer
la tâche coûteuse de remise à zéro de la
mémoire allouée par mmap(2). Trouver un compromis
entre ces effets mène à une valeur du paramètre
M_MMAP_THRESHOLD par défaut à 128*1024.
- La limite basse de ce paramètre est 0. La limite haute est
DEFAULT_MMAP_THRESHOLD_MAX : c'est-à-dire 512*1024
sur les systèmes 32 bits ou 4*1024*1024*sizeof(long)
sur les systèmes 64 bits.
- Note : de nos jours, la glibc configure ce seuil
dynamiquement. La valeur initiale est 128*1024, mais lorsque sont
libérés des blocs de taille supérieure au seuil mais
inférieure ou égale à
DEFAULT_MMAP_THRESHOLD_MAX, le seuil est ajusté à la
taille du bloc libéré. Quand le mécanisme de seuil
dynamique est activé, le seuil de désallocation du tas est
également configuré dynamiquement à deux fois le
seuil mmap. L'ajustement dynamique du seuil mmap est
désactivé dès lors qu'un des paramètres
M_TRIM_THRESHOLD, M_TOP_PAD, M_MMAP_THRESHOLD, ou
M_MMAP_MAX est configuré.
- M_MXFAST
(depuis glibc 2.3)
- Définir la limite supérieure (en octets) pour les
requêtes d'allocation mémoire qui sont satisfaites en
utilisant des « fastbins ». Les
« fastbins » sont des espaces de stockage qui
contiennent des blocs de mémoire désalloués de
même taille, sans fusion des blocs libres adjacents. La
réallocation ultérieure de blocs de cette taille peut
être effectuée très rapidement en allouant à
partir du « fastbin \[u00BB], bien que d'un autre
côté la fragmentation de la mémoire et l'empreinte
mémoire totale du programme puissent augmenter.
- La valeur par défaut de ce paramètre est
64*sizeof(size_t)/4 (c'est-à-dire 64 sur les
architectures 32 bits). La plage de ce paramètre va de
0 à 80*sizeof(size_t)/4. Fixer M_MXFAST
à 0 désactive l'utilisation des
« fastbins ».
- M_PERTURB
(depuis glibc 2.4)
- Si ce paramètre est configuré à une valeur non nulle,
tous les octets de mémoire allouée (autrement qu'avec
calloc(3)) sont initialisés au complément de la
valeur de l'octet le moins significatif de value. Lorsque la
mémoire allouée est libérée avec
free(3), les octets libérés prennent tous la valeur
de l'octet le moins significatif de value. Cette
fonctionnalité permet de détecter des erreurs lorsque les
programmes supposent que la mémoire allouée a
été initialisée à zéro, ou
réutilisent des valeurs depuis une zone mémoire
précédemment libérée.
- La valeur par défaut de ce paramètre est 0.
- M_TOP_PAD
- Ce paramètre définit la quantité en octets de
bourrage à utiliser lors de l'appel à sbrk(2) pour
modifier la taille du segment de données. Ce paramètre a un
effet dans les circonstances suivantes :
- Lorsque la taille du segment de données est augmentée,
M_TOP_PAD octets sont ajoutés à la requête
sbrk(2).
- Lorsque le tas est désalloué suite à l'appel
free(3) (voir M_TRIM_THRESHOLD), cet espace
supplémentaire est préservé en haut du tas.
- Dans tous les cas, la quantité de bourrage est toujours arrondie
à la taille d'une page système.
- La valeur M_TOP_PAD résulte d'un compromis entre
l'augmentation du nombre d'appels système (avec une valeur faible)
et le gaspillage de mémoire inutilisée en haut du tas (avec
une valeur élevée).
- La valeur par défaut de ce paramètre est 128*1024.
- M_TRIM_THRESHOLD
- Lorsque la quantité de mémoire libre et contigüe en
haut du tas dépasse ce seuil, free(3) utilise sbrk(2)
pour rendre cette mémoire au système d'exploitation. (Cela
peut être utile pour les programmes qui sont exécutés
encore longtemps après avoir libéré une
quantité importante de mémoire.)Le paramètre
M_TRIM_THRESHOLD indique la taille minimale (en octet) que ce bloc
de mémoire doit atteindre avant que sbrk(2) ne soit
utilisé pourréduire le tas.
- La valeur par défaut de ce paramètre est 128*1024, en
octets. Une valeur de -1 désactive complètement la
désallocation.
- La valeur M_TRIM_THRESHOLD résulte d'un compromis entre
l'augmentation du nombre d'appels système (avec une valeur faible)
et le gaspillage de mémoire inutilisée en haut du tas (avec
une valeur élevée).
Un certain nombre des paramètres de mallopt()
peuvent être modifiés à travers de variables
d'environnement. Ces variables ont l'avantage de ne pas nécessiter la
modification du code source du programme. Pour être prises en compte,
ces variables doivent être définies avant le premier appel
à une fonction d'allocation mémoire. Les paramètres
passés par la fonction mallopt() sont prioritaires devant ceux
issus des variables d'environnement. Pour des raisons de
sécurité, ces variables sont ignorées dans le cas de
programmes setuid ou setgid.
Les variables d'environnement sont les suivantes (notez le
caractère de soulignement
(« underscore ») qui les termine) :
- MALLOC_ARENA_MAX
- Contrôle du même paramètre que M_ARENA_MAX de
mallopt().
- MALLOC_ARENA_TEST
- Contrôle du même paramètre que M_ARENA_TEST de
mallopt().
- MALLOC_CHECK_
- Cette variable d'environnement contrôle le même
paramètre que M_CHECK_ACTION de mallopt(). Si elle
est configurée à une valeur non nulle, une mise en
œuvre spécifique des fonctions d'allocation mémoire
est utilisée, grâce à la fonctionnalité
malloc_hook(3). Cette mise en œuvre effectue des
vérifications d'erreurs supplémentaires, au prix d'un
ralentissement par rapport au jeu standard de fonctions d'allocation
mémoire. Cependant, elle ne détecte pas toutes les erreurs
possibles : des fuites mémoires peuvent encore se
produire.
- La valeur de cette variable d'environnement doit être un seul
chiffre, dont le sens est comme décrit pour M_CHECK_ACTION.
Tout caractère au-delà du premier chiffre est
ignoré.
- Pour des raisons de sécurité, MALLOC_CHECK_ est
ignoré par défaut dans le cas de programmes setuid ou
setgid. Cependant, si le fichier /etc/suid-debug existe (peu
importe son contenu), alors la valeur de MALLOC_CHECK_ est prise en
compte pour les programmes setuid ou setgid.
- MALLOC_MMAP_MAX_
- Contrôle du même paramètre que M_MMAP_MAX de
mallopt().
- MALLOC_MMAP_THRESHOLD_
- Contrôle du même paramètre que
M_MMAP_THRESHOLD de mallopt().
- MALLOC_PERTURB_
- Contrôle du même paramètre que M_PERTURB de
mallopt().
- MALLOC_TRIM_THRESHOLD_
- Contrôle du même paramètre que
M_TRIM_THRESHOLD de mallopt().
- MALLOC_TOP_PAD_
- Contrôle du même paramètre que M_TOP_PAD de
mallopt().
En cas de succès, mallopt() renvoie 1. En cas
d'erreur, il renvoie 0.
En cas d'erreur, errno n'est pas positionné.
Cette fonction n'est pas spécifiée par les normes
POSIX ou C. Une fonction similaire existe sur de nombreux
dérivés de System V, mais les valeurs permises de
param varient d'un système à l'autre. SVID
définit les options M_MXFAST, M_NLBLKS, M_GRAIN
et M_KEEP, mais seule la première d'entre elles est disponible
dans la glibc.
Indiquer une valeur non valable pour param ne
génère pas d'erreur.
Une erreur de calcul dans la mise en œuvre glibc implique
qu'un appel de la forme suivante :
mallopt(M_MXFAST, n)
n'active pas les « fastbins » pour
toutes les allocations d'une taille jusqu'à n. Pour obtenir
l'effet attendu, n doit être arrondi à un multiple
supérieur ou égal à (2k+1)*sizeof(size_t),
où k est un entier.
Si mallopt() est utilisé pour configurer
M_PERTURB, tous les octets de mémoire alloués sont
initialisés au complément de value, puis lorsque la
mémoire est libérée les octets sont initialisés
à value. Cependant, une erreur de sizeof(size_t) est
présente dans le code mis en œuvre : au lieu
d'initialiser précisément le bloc de mémoire
libéré par l'appel free(p), c'est le bloc
démarrant à p+sizeof(size_t) qui est
initialisé.
Le programme ci-dessous illustre l'utilisation de
M_CHECK_ACTION. Si le programme est appelé avec un
paramètre (entier), alors celui-ci est utilisé pour
M_CHECK_ACTION. Le programme alloue un bloc de mémoire, puis
le libère deux fois, ce qui constitue une erreur.
L'exemple de session ci-dessous montre ce qu'il se passe lorsqu'un
programme est exécuté avec la glibc et la valeur par
défaut de M_CHECK_ACTION :
$ ./a.out
main(): fin du premier appel free()
*** glibc detected *** ./a.out: double free or corruption (top): 0x09d30008 ***
======= Backtrace: =========
/lib/libc.so.6(+0x6c501)[0x523501]
/lib/libc.so.6(+0x6dd70)[0x524d70]
/lib/libc.so.6(cfree+0x6d)[0x527e5d]
./a.out[0x80485db]
/lib/libc.so.6(__libc_start_main+0xe7)[0x4cdce7]
./a.out[0x8048471]
======= Memory map: ========
001e4000-001fe000 r-xp 00000000 08:06 1083555 /lib/libgcc_s.so.1
001fe000-001ff000 r--p 00019000 08:06 1083555 /lib/libgcc_s.so.1
[some lines omitted]
b7814000-b7817000 rw-p 00000000 00:00 0
bff53000-bff74000 rw-p 00000000 00:00 0 [stack]
Abandon
L'exemple suivant montre les cas d'autres valeurs de
M_CHECK_ACTION:
$ ./a.out 1 # Diagnostique l'erreur et continue
main(): fin du premier appel free()
*** glibc detected *** ./a.out: double free or corruption (top): 0x09cbe008 ***
main(): fin du second appel free()
$ ./a.out 2 # Interrompt le programme sans message d'erreur
main(): fin du premier appel free()
Abandon
$ ./a.out 0 # Ignore l'erreur et continue
main(): fin du premier appel free()
main(): fin du second appel free()
L'exemple suivant montre comment configurer le même
paramètre avec la variable d'environnement
MALLOC_CHECK_ :
$ MALLOC_CHECK_=1 ./a.out
main(): fin du premier appel free()
*** glibc detected *** ./a.out: free(): invalid pointer: 0x092c2008 ***
main(): fin du second appel free()
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char *argv[])
{
char *p;
if (argc > 1) {
if (mallopt(M_CHECK_ACTION, atoi(argv[1])) != 1) {
fprintf(stderr, "échec de mallopt()");
exit(EXIT_FAILURE);
}
}
p = malloc(1000);
if (p == NULL) {
fprintf(stderr, "échec de malloc()");
exit(EXIT_FAILURE);
}
free(p);
printf("%s(): fin du premier appel free()\n", __func__);
free(p);
printf("%s(): fin du second appel free()\n", __func__);
exit(EXIT_SUCCESS);
}
mmap(2), sbrk(2), mallinfo(3),
malloc(3), malloc_hook(3), malloc_info(3),
malloc_stats(3), malloc_trim(3), mcheck(3),
mtrace(3), posix_memalign(3)
La traduction française de cette page de manuel a
été créée par Christophe Blaess
<https://www.blaess.fr/christophe/>, Stéphan Rafin
<stephan.rafin@laposte.net>, Thierry Vignaud
<tvignaud@mandriva.com>, François Micaux, Alain Portal
<aportal@univ-montp2.fr>, Jean-Philippe Guérard
<fevrier@tigreraye.org>, Jean-Luc Coulon (f5ibh)
<jean-luc.coulon@wanadoo.fr>, Julien Cristau
<jcristau@debian.org>, Thomas Huriaux
<thomas.huriaux@gmail.com>, Nicolas François
<nicolas.francois@centraliens.net>, Florentin Duneau
<fduneau@gmail.com>, Simon Paillard
<simon.paillard@resel.enst-bretagne.fr>, Denis Barbier
<barbier@debian.org>, David Prévot <david@tilapin.org> et
Grégoire Scano <gregoire.scano@malloc.fr>
Cette traduction est une documentation libre ; veuillez
vous reporter à la
GNU General
Public License version 3 concernant les conditions de copie et de
distribution. Il n'y a aucune RESPONSABILITÉ LÉGALE.
Si vous découvrez un bogue dans la traduction de cette page
de manuel, veuillez envoyer un message à
debian-l10n-french@lists.debian.org.