malloc()
?NULL
les pointeurs après un free()
?free()
ne met pas les pointeurs à NULL
?malloc()
et calloc()
?malloc()
?malloc()
, cette fonction est-elle buggée ?realloc()
malloc()
?
Certains intervenants pensent que caster la valeur de retour
de malloc()
est inutile, voire dangereux.
En effet, malloc()
renvoie un void *
.
Or, en C, un pointeur void *
est implicitement casté
lors d'une affectation vers le type de la variable affectée.
Bien sûr, expliciter le cast n'est pas interdit, et est parfois
utile.
Toutefois, caster le retour de malloc()
risque de cacher au compilateur l'oubli du prototype de
malloc()
.
Ce prototype se trouve dans le fichier d'en-tête <stdlib.h>
.
Sans lui, malloc()
sera par défaut une fonction
retournant un int
et dont les paramètres seront du type
des arguments passés, ce qui peut provoquer de sérieux bugs.
La véritable erreur est l'oubli du fichier d'en-tête
<stdlib.h>
, et non pas le cast de malloc()
en
lui même.
Mais le cast de malloc()
risque de cacher au compilateur
cette erreur.
À noter qu'il existe des outils de vérification de code et des
options sur la plupart des compilateurs4 qui permettent de détecter ce genre d'erreur.
D'autres intervenants jugent qu'il faille tout de même caster le
retour de malloc()
, afin de conserver une compatibilité
avec d'anciens compilateurs pré-ANSI, ou pour intégrer plus
facilement le code avec C++.
Evidemment, les programmeurs avertis sauront dans quelles
situations il est utile ou non de caster les void *
.
Voir aussi la question 7.8
var_t * ma_var = malloc(N * sizeof *ma_var);
Si le type de la variable change, l'allocation est toujours
valide. À noter que l'on ne caste pas le retour de
malloc()
Voir la question 12.1 à ce sujet, ainsi que la question 12.10.
NULL
les pointeurs après un free()
?free()
libère l'espace mémoire pointé par
le pointeur en question. Mais la valeur de celui-ci ne peut-être
changée, car en C les arguments sont passés par valeur aux
fonctions.
La variable pointeur contient après le free()
une
adresse invalide.
Son utilisation peut entraîner de sérieux embêtements.
Pour éviter cela, une bonne solution consiste à affecter la valeur
NULL
au pointeur après l'appel à free()
.
Il existe aussi certaines implémentations de l'allocation
dynamique qui fonctionnent en Garbage Collector,
c'est-à-dire, que la mémoire n'est réellement libérée que lorsque
le pointeur est mis à NULL
.
Dans tous les cas, cela permet de tester facilement la validité des pointeurs.
free()
ne met pas les pointeurs à NULL
?free()
.
Mais ce n'est pas le cas, il faut donc le faire soi-même.
malloc()
et calloc()
?calloc()
est équivalent à :
/* p = calloc(m, n); */
p = malloc(m * n);
memset(p, 0, m * n);
Chaque élément est initialisé à 0
. Ce 0
est un « tout bit à zéro ».
La valeur des éléments n'est pas forcément valide, suivant leur type.
Voir aussi la question 5.6.
malloc()
?stdlib.h
.
Voir à ce sujet la question 12.1.
malloc()
, cette fonction est-elle buggée ?malloc()
. Les sources les plus plausibles
du problème sont :
malloc(strlen(s))
au lieu de
malloc(strlen(s)+1)
.
Voir aussi les questions 12.2 et 12.8.
NULL
qui en est la cause.
Ce genre d'erreur peut aussi provenir d'une mauvaise allocation
(cf. 12.7 et
12.2)
ou de l'oubli du 0
en fin de chaîne.
realloc()
realloc()
permet de modifier la taille de
l'espace mémoire alloué à une variable.
Elle est souvent utilisée pour augmenter cette taille.
Rappelons que la mémoire allouée par malloc()
,
calloc()
et realloc()
est fournie sous la
forme d'une zone continue (en un seul bloc).
Or, il peut arriver que la nouvelle taille demandée dépasse l'espace
disponible derrière la zone initiale.
Dans ce cas, la fonction realloc()
alloue une nouvelle
zone ailleur, là ou il y a de la place, et y recopie les données
initiales. L'ancienne zone est alors libérée.
C'est pourquoi realloc()
renvoie un pointeur sur
la nouvelle zone mémoire, même si l'augmentation de taille (ou la
réduction) a pu se faire sur place.
Bien sûr, comme malloc()
, realloc()
peut
échouer.
Voici pour résumer une bonne manière d'utiliser
realloc()
:
#include <stdlib.h> /* pour realloc() et free() */
/* ... */
int * var = NULL ;
var = malloc(sizeof * var * 42) ;
if (!var) {
/* gestion des erreurs */
}
/* ... */
int * tmp = NULL ;
tmp = realloc(var, 84) ;
if (tmp) {
var = tmp ;
}
else {
/* gestion de l'erreur */
}
faq-fclc 5/3/2002 (8h 59:05)