Vous êtes sur la page 1sur 7

malloc, calloc, realloc et free Allocation/dsallocation dynamique de mmoire

Il se peut que dans vos programmes vous ayez besoin des tableaux, mais il se peut galement que vous ne sachiez pas l'avance la taille du tableau en question, parfois celle-ci peut tre calcule ou dtermine par l'utilisateur. Jusqu' prsent, vous n'avez fait qu'allouer des tableaux plus grand que ce qu'ils devaient contenir, mais maintenant vous allez apprendre une technique pour allouer dynamiquement vos tableaux, c'est dire que la taille de celui-ci ne devra pas tre connue avant l'allocation du tableau, pour cela nous allons passer par les pointeurs et les fonctions de types malloc, calloc, realloc et free. Ces 3 fonctions se trouvent dans la bibliothque de fonctions stdlib.h, n'oubliez donc pas de l'inclure. Chaque fonction a sa spcificit, vous allez voir.

malloc

Voici la plus connue des fonctions d'allocation de mmoire. malloc sert justement allouer de la mmoire, il vous suffit de lui passer les bons arguments et malloc alloue la taille mmoire voulue et renvoie l'adresse du premier octet de cet emplacement mmoire, il faudra donc avoir un pointeur pour rcuprer cette adresse. L'argument de malloc est simplement la taille allouer, mais attention ici, si vous tapez 3, le programme vous allouera 3 octets en mmoire c'est tout, il ne multipliera pas lui mme par 4 pour avoir 12 octets, vous allez donc devoir le faire vous mme et ce, grace la fonction sizeof vu dans le cours prcdent, regardez plus le code suivant :

view plain

print

01. 02. 03. 04. 05. 0 . 0%. 0'. 0(. 10. 11. 12. 13. 14. 15. 1 . 1%. 1'. 1(. 20. 21. 22. 23. 24. 25. 2 . 2%. 2'.

#include <stdio.h> #include <stdlib.h> int main() { int nombre = 0; int !tableau = "#$$; int & = 0; )rint* (+,euille- entrer la taille du tableau . +); scan* (+/d+0 1nombre); tableau = malloc(sizeof(int) ! nombre); for (& = 0; & < nombre; 22&) { )rint* (+,euille- entrer un nombre . +); scan* (+/d+0 1tableau3&4); 5 for (& = 0; & < nombre; 22&) { )rint* (+"ombre /d . /d6n+0 (& 2 1)0 tableau3&4); 5 *ree(tableau); return 0; 5

Nous commenons par dclarer une variable entire qui contiendra 0. Ensuite, nous dclarons un pointeur, tant que maintenant il ne contient aucune adresse, effectivement, lorsque nous crons un pointeur, rien en mmoire n'est allou mais il contiendra quand mme quelques crasses, donc par prcaution nous l'initialisons NULL (pour les variables, cela vaut 0). Nous dclarons ensuite une variable x qui servira de variable de contrle de boucle. Ensuite, nous demandons l'utilisateur d'entrer la taille du tableau que nous rcuprerons dans la variable nombre. C'est l que ca devient interessant. Maintenant que nous avons la taille du tableau, nous allons allouer en mmoire la place pour ce tableau en utilisant la fonction malloc. Comme je l'ai dit plus haut, malloc ne prend qu'un argument et celui-ci est la taille en octets qui devra tre alloue en mmoire. Si l'utilisateur rentre 5, il ne faudra pas allouer 5 octets en mmoire car on veut stocker des variables int qui prennent 4 octets chacune, il faudra donc allouer 5 fois la taille d'une variable de type int et comme je l'ai dit dans le cours prcdent, on peut rcuprer la taille d'un type de variable grace l'instruction sizeof, nous multiplions donc la taille d'un int (sizeof(int)) par la taille du tableau souhaite (* nombre). Une fois ceci fait, nous faisons deux boucles for. La premire va demander l'utilisateur d'entrer les nombres du tableaux et la seconde va les afficher. Ces boucles sont l simplement pour vous montrer qu'une fois allou, le pointeur peut tre utilis comme un tableau d'une manire conventionnelle. Vous verrez dans un autre cours comment faire la mme chose avec des structures cres par vous-mme, je me contente juste des type de base dans ce cours. Comme vous le voyez, il reste une ligne dans notre programme que je n'ai pas explique, celle qui contient l'instruction free. En fait, quand vous dclarez une variable normale, par exemple la variable nombre, le programme alloue lui-mme la mmoire et lorsque le programme se ferme, il dsalloue lui mme la mmoire sans qu'on aie lui demander, par contre, avec les pointeurs c'est diffrent, effectivement, le programme n'est pas cens savoir la taille du tableau que l'on a allou, nous devrons donc dsallouer la mmoire nous mme et pour cela, il faut utiliser la fonction free. Celle-ci ne prend qu'un paramtre, le pointeur dsallouer. Une fois le free excut, votre tableau ne sera plus utilisable, il faudra refaire un malloc pour pouvoir l'utiliser.

calloc

La fonction malloc ne servait pas vraiment intialiser un tableau de donne mais plutot une partie de la mmoire, la fonction calloc, elle, est conue exprs pour allouer la mmoire ncessaire pour un tableau, et en plus, la fonction remplit cette zone mmoire de 0. La syntaxe de la fonction calloc diffre quelque peu de celle de la fonction malloc, effectivement, celle-ci prend le nombre d'lment que devra contenir le tableau et la taille de chaque lment. Donc au lieu de faire la multiplication du malloc, nous la sparons en deux arguments, nous aurions donc pu raliser le programme suivant comme suit :

view plain

print

01. 02. 03.

#include <stdio.h> #include <stdlib.h>

04. 05. 0 . 0%. 0'. 0(. 10. 11. 12. 13. 14. 15. 1 . 1%. 1'. 1(. 20. 21. 22. 23. 24. 25. 2 . 2%. 2'.

int main() { int nombre = 0; int !tableau = "#$$; int & = 0; )rint* (+,euille- entrer la taille du tableau . +); scan* (+/d+0 1nombre); tableau = calloc(nombre0 sizeof(int)); for (& = 0; & < nombre; 22&) { )rint* (+,euille- entrer un nombre . +); scan* (+/d+0 1tableau3&4); 5 for (& = 0; & < nombre; 22&) { )rint* (+"ombre /d . /d6n+0 (& 2 1)0 tableau3&4); 5 *ree(tableau); return 0; 5

Comme vous le voyez, nous avons juste chang la fonction malloc en fonction calloc. Comme je l'ai dit, il suffit de mettre en premier argument la taille du tableau, et dans le deuxime argument la taille de chaque lment. Personnellement, part que calloc initialise la zone mmoire 0, je ne vois pas de grande diffrence entre malloc et calloc, c'est d'ailleurs pour cela que la plupart du temps, j'utilise malloc, maintenant vous de voir ce que vous dsirez. Et comme vous le voyez, nous dsallouons galement la mmoire avec free.

realloc

Il arrive galement qu'on alloue dynamiquement de la place en mmoire et qu'on se rende compte par aprs que la taille n'est pas suffisante. Par exemple, si on alloue 500 octets pour contenir 125 nombres et qu'on se rend compte aprs qu'en fait il y a 200 nombres, il va falloir rallouer de la mmoire, mais nous n'allons pas passer notre temps tout sauver et tout recopier, nous allons utiliser la fonction realloc. Celle-ci reoit deux arguments : le premier tant le pointeur contenant l'adresse redimensionner et le deuxime tant la nouvelle taille du tableau, regardez par exemple le programme suivant :

view plain

print

01. 02.

#include <stdio.h> #include <stdlib.h>

03. 04. 05. 0 . 0%. 0'. 0(. 10. 11. 12. 13. 14. 15. 1 . 1%. 1'. 1(. 20. 21. 22. 23. 24. 25. 2 . 2%. 2'. 2(. 30. 31. 32. 33. 34. 35.

int main() { int nombre = 0; int !tableau = "#$$; int & = 0; )rint* (+,euille- entrer la taille du tableau . +); scan* (+/d+0 1nombre); tableau = malloc(sizeof(int) ! nombre); for (& = 0; & < nombre; 22&) { )rint* (+,euille- entrer un nombre . +); scan* (+/d+0 1tableau3&4); 5 for (& = 0; & < nombre; 22&) { )rint* (+"ombre /d . /d6n+0 (& 2 1)0 tableau3&4); 5 tableau = realloc(tableau0 sizeof(int) ! (nombre 2 1)); tableau3nombre4 = 100; for (& = 0; & < nombre 2 1; 22&) { )rint* (+"ombre /d . /d6n+0 (& 2 1)0 tableau3&4); 5 *ree(tableau); return 0; 5

Comme vous voyez, le dbut du code ne change pas, on alloue un tableau de la taille dsire, on le remplit de valeur et on les affiche, jusque l rien de nouveau. Mais voil, on va maintenant augmenter la taille du tableau de 4 octets pour retenir un nombre supplmentaire. Nous utilisons donc realloc. Nous passons donc comme premier argment tableau, qui est le pointeur que l'on va redimenssioner et comme deuxime argument, la nouvelle taille du tableau, donc un emplacement en plus que le nombre d'origine multipli par la taille d'un int. Cette fonction renverra l'adresse de la nouvelle zone mmoire que nous stockerons ensuite dans tableau. Ensuite, nous ajoutons le nombre 100 comme dernier lment du tableau et ensuite, nous raffichons le tableau pour montrer que la valeur 100 a bien t ajoute. Enfin, nous dsallouons le tableau.

Test de mmoire

Jusqu' prsent, je n'ai fait aucun test, mais vous DEVEZ absolument les faire. Effectivement, il se peut que l'allocation mmoire ne se passe pas bien (problme interne, manque de mmoire libre, demande trop volumineuse,...), il est donc important de vrifier si celle-ci s'est bien passe, sans quoi votre programme ne fonctionnera pas correctement. Comment faire ? C'est simple, malloc, calloc et realloc renvoie NULL si l'allocation dynamique foire, donc dans le cas de malloc et de calloc, il suffit de tester la valeur du pointeur

aprs allocation :

view plain

print

01. 02. 03. 04. 05. 0 . 0%. 0'. 0(. 10. 11. 12. 13. 14. 15. 1 . 1%. 1'. 1(. 20. 21. 22. 23. 24. 25. 2 . 2%. 2'. 2(. 30. 31.

#include <stdio.h> #include <stdlib.h> int main() { int nombre = 0; int !tableau = "#$$; int & = 0; )rint* (+,euille- entrer la taille du tableau . +); scan* (+/d+0 1nombre); tableau = malloc(sizeof(int) ! nombre); if (tableau == "#$$) return 71; for (& = 0; & < nombre; 22&) { )rint* (+,euille- entrer un nombre . +); scan* (+/d+0 1tableau3&4); 5 for (& = 0; & < nombre; 22&) { )rint* (+"ombre /d . /d6n+0 (& 2 1)0 tableau3&4); 5 *ree(tableau); return 0; 5

Ce code est le mme que le premier, sauf qu'ici, nous vrifions si l'allocation mmoire s'est bien passe en testant si la valeur du pointeur est bien diffrente de NULL. Si ce n'est pas le cas, nous quittons la fonction en renvoyant la valeur -1 (0 tant une sortie normale du programme). Pourquoi n'ai-je pas inclus realloc dans le tas ? Simplement parce qu'il est prfrable pour cette fonction de passer par un pointeur secondaire. Pourquoi ? Parce qu'en faisant comme j'ai montr dans l'exemple concernant realloc, si il y a un problme d'allocation, la valeur du pointeur sera crase par NULL et toute les donnes de votre tableau seront perdues, il est donc prfrable de passer par un pointeur temporaire :

view plain

print

01. 02. 03. 04. 05. 0 . 0%. 0'. 0(.

#include <stdio.h> #include <stdlib.h> int main() { int int int int nombre = 0; !tableau = "#$$; !tem) = "#$$; & = 0;

10. 11. 12. 13. 14. 15. 1 . 1%. 1'. 1(. 20. 21. 22. 23. 24. 25. 2 . 2%. 2'. 2(. 30. 31. 32. 33. 34. 35. 3 . 3%. 3'. 3(. 40. 41. 42.

)rint* (+,euille- entrer la taille du tableau . +); scan* (+/d+0 1nombre); tableau = malloc(sizeof(int) ! nombre); for (& = 0; & < nombre; 22&) { )rint* (+,euille- entrer un nombre . +); scan* (+/d+0 1tableau3&4); 5 for (& = 0; & < nombre; 22&) { )rint* (+"ombre /d . /d6n+0 (& 2 1)0 tableau3&4); 5 tem) = realloc(tableau0 sizeof(int) ! (nombre 2 1)); if (tem) 8= "#$$) tableau = tem); else return 71; tableau3nombre4 = 100; for (& = 0; & < nombre 2 1; 22&) { )rint* (+"ombre /d . /d6n+0 (& 2 1)0 tableau3&4); 5 *ree(tableau); return 0; 5

Comme vous le voyez, nous rcuprons d'abord dans le pointeur temp la valeur renvoye par realloc, si cette valeur est bien diffrente de NULL, nous changeons les adresses mmoires et la plaons dans la variable tableau, sinon, on quitte le programme. N'hsitez pas relire ce cours plusieurs fois, car vous devez connaitre ces 4 fonctions sur le bout des doigts, car on les utilise normment, je les utiliserai d'ailleurs encore beaucoup dans les prochains cours sur les pointeurs.