Cours 11.3. Allocation mémoire dynamique

Allocation mémoire

Supposons que l'on veuille écrire un programme qui charge un texte depuis un fichier. On ne peut pas savoir a priori quelle sera la taille du texte. C'est un problème pour la déclaration de la chaîne de caractères qui va contenir ce texte. La solution à ce problème est l'allocation dynamique. Si l'on déclare une chaîne de 999 caractères, cette taille sera fixé au moment de la compilation et immuable. C'est un problème si le fichier contient 2000 caractères.

char text[1000];

La solution consiste à déclarer un pointeur de caractères, puis allouer la mémoire nécessaire sur demande :

char * text;
text = malloc(1000 * sizeof(char));

Malloc

malloc() est une fonction de la bibliothèque C standard stdlib.h. malloc signife Memory ALLOCation. Cette fonction permet d'allouer (de réserver) un bloc de mémoire d'une taille définie.

#include <stdlib.h>
void* malloc(size_t size)

La fonction malloc() alloue un bloc de mémoire de size octets et retourne l'adresse du début du bloc. Si malloc() ne réussit pas à allouer la mémoire, la fonction retourne un pointeur nul (0). Notons que, comme pour les tableaux, le bloc de mémoire est nécessairement d'un seul tenant.

Le type de la fonction est void*, ce qui pourrait à premier abord paraître paradoxal, en réalité, cela signifie que la fonction retourne un pointeur sans type associé. À charge du développeur de caster le pointeur pour le convertir dans le type désiré :

// Déclare un pointeur d'entiers
int * buffer;

// Alloue 200 entiers pour le buffer
buffer =(int*)malloc(200 * sizeof(int));

buffer pourra être utilisé exactement comme un tableau :

buffer[199] = 30;

Free

La fonction free permet de libérer de la mémoire précédemment allouée.

void free (void* ptr);

Reprenons l'exemple précédent, lorsque buffer n'est plus utilisé, il est possible de désallouer (libérer) la mémoire :

// Alloue dynamiquement un tableau 200 entiers
int * buffer;
buffer =(int*)malloc(200 * sizeof(int));

...

// Libère la mémoire utilisée par le tableau
free (buffer);

Une erreur classique lorsqu'on utilise l'allocation dynamique est d'allouer de la mémoire, mais d'oublier de la libérer. Le programme reserve de plus en plus de bloc mémoire, mais ne les libère pas (ou que partiellement). Le programme finit par utiliser toute la mémoire disponible et

Voici un exemple de code qu'il faut absolument éviter :

char* buffer;
while (1) {
  // Alloue 10Mo
  buffer = (char*)malloc(1e7);
  ...
  // Pas d'appel à free(buffer);
}

Ce code a été exécuté sur un PC avec 32Go de RAM. Il faut moins d'une minute pour planter la machine :

Fuite mémoire lors de l'allocation dynamique

Realloc

La fonction realloc permet de modifier (augmenter ou diminuer) la taille d'un bloc précédemment alloué. Voici un exemple :

float tab*;
// Alloue un tableau de 100 flottants
tab = (float*)malloc(100 * sizeof(float));

...

// Modifie la tableau pour 500 cellules 
tab = (float*)realloc(tab, 500 * sizeof(float));

Notons que la fonction realloc() peut modifier l'adresse du pointeur si nécessaire. Dans ce cas, les données initiales seront copiées dans le nouveau bloc. Si le nouveau bloc est plus grand, l'excédent contiendra des valeurs arbitraires.

Exercice

Écrire un programme qui

Combien de cellules dans le tableau : 50
1 4 9 19 8 10 10 9 15 10 2 19 20 4 20 7 3 15 16 16 17 14 12 9 2 5 5 13 1 19 5 0 3 12 17 9 1 7 16 16 15 18 12 14 20 10 20 2 2 15

Tester le programme avec dix milliards de cellules dans le tableau :

Combien de cellules dans le tableau : 10000000000
Pas assez de mémoire
exit status 1

Quiz

À quoi sert l'allocation dynamique ?

Vérifier Bravo ! L'allocation dynamique permet d'alouer la mémoire à la volée. Essaie encore ...

Que fait le code suivant ?

buffer = (int*)malloc(1000);
Vérifier Bravo ! Le paramètre de malloc() est la taille en octets. Essaie encore ...

Qu'est-ce qu'une fuite mémoire ?

Vérifier Bravo ! Une fuite mémoire est une allocation continue de mémoire sans qu'elle ne soit jamais libérée. Essaie encore ...

Avec la fonction realloc() ...

Vérifier Bravo ! realloc() permet d'augmenter ou de diminuer un espace mémoire précédemment alloué dynamiquement. Essaie encore ...

Que va-t-il advenir du pointeur ptr ?

ptr = (char*)realloc(ptr, 100);
Vérifier Bravo ! Lors de la réallocation, l'adresse du pointeur peut être modifiée. Si la réallocation échoue, la fonction retourne le pointer NULL. Essaie encore ...

Voir aussi


Dernière mise à jour : 29/11/2022