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()
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;
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 :
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.
Écrire un programme qui
*ptr
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