Introduction au langage C/Allocation dynamique de mémoire
Les tableaux en C permettent de ranger des informations et de s'y référer par un numéro, l'index. Dans l’utilisation la plus simple de ces tableaux, on fixe les limites du tableau en écrivant le code. La gestion de la mémoire se fait alors de manière automatique. On peut en revanche décider ou avoir besoin de gérer soi-même la taille du tableau alors que le programme est en cours d'exécution. Faire cela s’appelle « allouer dynamiquement » de la mémoire au programme.
Introduction
[modifier | modifier le wikicode]On utilise beaucoup plus souvent l'allocation automatique (où c’est le programme qui se charge de tout) que l'allocation dynamique, mais cela s'avère parfois être l'unique solution.
Un exemple d'allocation automatique serait la déclaration d'une variable, le programme alloue de la mémoire à la déclaration de la variable et à la fin du bloc la variable est automatiquement supprimée par le programme. Ceci est très pratique pour les types de bases, mais il peut être intéressant d’utiliser l'allocation dynamique pour créer des tableaux d'une taille indéfinie lors de l'exécution du programme.
Un exemple d’utilisation de l'allocation dynamique : vous souhaitez que l'utilisateur entre une série de chiffres, mais ne savez pas combien d'éléments comportera cette série. Vous pourriez préparer un certain nombre de places n, et occuper uniquement celles qui vous servent — mais cela vous limiterait à n entrées, et utiliserait de toute manière la place mémoire pour n données. L'allocation dynamique de mémoire vous permet de redéfinir la taille du tableau en cours d'exécution, d'ajouter ou supprimer des entrées, sans limites ou presque.
Taille des variables
[modifier | modifier le wikicode]Tous les types de variables occupent une certaine place en mémoire, une quantité d'espace qui s'exprime en octets. Selon que vous créez une variable de type short
ou de type int
, vous avez ainsi besoin de plus ou moins de mémoire. De plus, selon le système considéré, un même type peut occuper une place différente.
Pour connaître la place que prend en mémoire un certain système, il suffit d’utiliser l'opérateur sizeof
.
Par exemple pour connaître la taille d'un int
sur le système il vous suffit de faire:
Attention : sizeof() n’est pas une fonction, c’est un opérateur. C’est pour cela que cette instruction sera remplacée à la compilation par la taille du type int par le compilateur. Si vous compilez sur un système, c’est la valeur pour ce système qui sera enregistrée, quelle que soit la machine sur laquelle vous exécuterez le programme.
|
Allocation dynamique
[modifier | modifier le wikicode]L'allocation dynamique se fait par le biais de la fonction malloc()
qui permet d'allouer un certain nombre d'octets et qui renvoie un pointeur sur cette case mémoire allouée.
Voici le prototype de la fonction malloc()
:
Le type void
est un passe-partout, il permet de remplacer n’importe quel autre type.
Ainsi pour allouer dynamiquement un int
il suffit de faire :
Vérifier que l'allocation a été un succès
[modifier | modifier le wikicode]Pour vérifier que l'allocation a été un succès, il suffit de tester le pointeur.
Si celui ci vaut NULL
alors l'allocation a échoué sinon l'allocation a réussi.
int *p = malloc(sizeof(int));
if(p == NULL)
{
perror("Echec allocation memoire");
exit(1);
}
Libération de la mémoire
[modifier | modifier le wikicode]Pour libérer la mémoire c’est tout aussi facile. La fonction qui permet de libérer de la mémoire est free()
, elle attend comme unique paramètre le pointeur sur la case mémoire à libérer.
N'oubliez pas de libérer la mémoire lorsque vous ne l'utilisez pas, surtout dans une structure répétitive. Sans cela, il y aura des « fuites » — des cases mémoires inutilisées mais bloquées par l'allocation (en anglais memory leak). Ce gaspillage pourrait aussi conduire à la consommation de toute la mémoire qui vous est autorisée et provoquer l'arrêt brutal de votre programme.
Allocation dynamique d'un tableau
[modifier | modifier le wikicode]Quelle taille prend un tableau de 5 int
? Réponse : 5 * sizeof(int)
.
Ainsi, pour créer un tableau de 5 int
il suffit de faire :
Comment faire un tableau de taille variable ? Vous pourriez penser écrire :
Ceci était interdit en C89, il fallait faire une allocation dynamique comme vu précédemment. Mais C99 a introduit les tableaux de taille variables (VLA : Variable Length Array) qui résolvent une partie des problèmes. Cependant leur passage en paramètre à une fonction oblige de transmettre aussi les tailles de leurs dimensions, certaines fonctions écrites avant C99 comme qsort de stdlib.h ne supporte pas ce mécanisme et nécessitent pour être utilisées des tableaux allouées dynamiquement de la façon suivante :
Encore une fois n'oubliez pas de libérer la mémoire à la fin du programme. Une autre fonction existe pour créer des tableaux dynamiquement, son prototype est:
Pour créer un tableau de taille variable vous devez faire :
Allocation dynamique d'un tableau à "n" dimensions
[modifier | modifier le wikicode]Il peut être utile de créer des tableaux dynamiques à plusieurs dimensions. Dans ce cas, il faut créer des indirections de pointeurs multiples.
unsigned int x;/*unsigned car les nombres négatifs ne sont pas pertinents ici.*/
unsigned int y;/*unsigned car les nombres négatifs ne sont pas pertinents ici.*/
unsigned int i;
unsigned int j;
int **tab;
x = 2;
y = 3;
tab = malloc(x * sizeof(*tab));
for (i = 0; i < x; i++)
{
tab[i] = malloc(y * sizeof(**tab));
for(j = 0; j < y; j++)
{
tab[i][j] = i * x + j;
}
}
/*...Do something here...*/
for (i = 0; i < x; i++)
{
free(tab[i]);
}
free(tab);