Allocation dynamique de la mémoire
Transcription
Allocation dynamique de la mémoire
Algorithmique P2 Gestion dynamique de la mémoire Renaud Dumont, Ulg 2009-2010 Allocation de mémoire 3 types de variables ◦ Statiques (variables globales ou locales statiques) Emplacement mémoire bien défini lors de la compilation adresses max var. loc. 1 var. loc. 2 var. loc. 3 pile Z o n e ◦ Automatiques (variables locales) Taille non définie a priori Créées et détruites au fur et à mesure de l'exécution Alloc. sur la pile ("stack"), qui croît ou décroît selon la durée de vie des fonctions Gestion transparente pour le programmeur ◦ Dynamiques Taille non définie a priori Créées et détruites par demande explicite Alloc. sur le tas ("heap"), qui croît ou décroît selon les instructions du programmeur… adresses min var. dyn. 2 var. dyn. 1 var. stat. 3 var. stat. 2 var. stat. 1 code exécutable tas m é m o i r e Allocation de mémoire #include <stdlib.h> int resultat = 0; int a = 1; 0 3 a somme j 5 3 a somme 5 1 a 1 a 0 résultat 6 résultat int main(){ int a; int somme = 3; int *j = malloc(sizeof(int)); *j = 5; resultat = somme + 3; a = 5; free(j); return 0; } code exécutable code exécutable Allocation Fail : exemple Soit une machine Solaris 64bits (taille pile : 8Mo) Dépassement de pile ◦ ok si BUFSZ = 1.000.000 Double sur 8 octets H Feldman, http://onlamp.com/pub/a/onlamp/2005/11/23/memory-management-2.html Allocation de mémoire : problème Limitations des variables statiques ◦ Problèmes avec les variables de taille importante ◦ Comment implémenter des structures dont la taille est inconnue à l'avance ? Listes, arbres, … Tableaux à dimension variable … Allocation Fail : solution Ne pas utiliser l'allocation sur la pile car sa taille dépend de plusieurs critères ◦ Selon le langage, l'architecture processeur, la taille de la mémoire vive Mais plutôt l'allocation dynamique, sur le tas double *num; num = (double *) malloc (BUFSZ* sizeof(double)); Allocation dynamique Lorsqu’on déclare le pointeur double *num, le compilateur réserve un entier pour stocker l’adresse vers laquelle pointe num. ◦ Il ne réserve pas de place pour l’objet pointé par num Soit la place a déjà été réservée lors d’une déclaration précédente : double d; double *num; … num=&d; Soit on doit réserver pour *num un espace-mémoire de taille adéquate. L’adresse de cet espace-mémoire sera la valeur de num. Cette réservation d'espace porte le nom d'allocation dynamique La fonction malloc Void * malloc (size_t taille) malloc renvoie un pointeur ◦ Fournit un pointeur nul (NULL) si l'allocation a échoué. ◦ Permet l'arithmétique des pointeurs. Size_t est un type prédéfini dépendant de l'implémentation La taille maximale de l'allocation l'est donc aussi Le contenu de la zone allouée est imprévisible La fonction malloc malloc(nbr_octets) réserve un emplacement de nbr_octets octets sur le tas et fournit l'adresse en retour #include <stdlib.h> … char * adr; … adr = malloc (50); … La fonction malloc On peut aussi spécifier la taille à allouer par la fonction sizeof(type) ◦ Celle-ci renvoie le nombre d’octets nécessaire pour stocker un objet du type type #include <stdlib.h> … char * adr; … adr = malloc (10*sizeof(char)); … ◦ Utile pour allouer l'espace nécessaire pour des objets de taille difficile à déterminer ( struct) La fonction malloc - Exemple Le cast n'est plus nécessaire (pour autant que stdlib.h soit inclus) La fonction malloc - exemple p+1 correspond à l'adresse de p + 1 * sizeof(int) De manière générale, p+i sera l'adresse de p + sizeof(type) fois i Free Gérer la mémoire = allocation + ◦ Pouvoir en récupérer lorsque l'emplacement attribué n'est plus nécessaire. ◦ Autrement dit, quand le pointeur p devient inutile. Il faut libérer cette place en mémoire. ◦ Il est aussi important d’allouer correctement la mémoire que de la libérer correctement. L’instruction free(p) libère la mémoire utilisée par l’objet pointé par p ◦ A toute instruction de type malloc doit être associée une instruction de type free. ◦ Chercher à libérer quelque chose qui n'a pas été alloué par malloc ou calloc est une erreur Free - exemple Free - exemple Grâce à free(adr1), l'espace ainsi libéré est réalloué à adr3 Pourquoi l'allocation demande-t-elle plus de place ? Calloc Void * calloc (size_t nb_blocs, size_t taille) Alloue l'emplacement nécessaire à nb_blocs consécutifs, ayant chacun une taille de taille octets. Remet à zéro chaque octet ainsi alloué La libération se fait en un bloc (puisque considéré comme tel par le système) Calloc … int *s, *t; s = malloc(50 * sizeof(int)); t = calloc(50, sizeof(int)); … Permet l'allocation de plus d'espace mémoire (size_t*size_t) que malloc (size_t) L'allocation de p blocs de n octets (calloc) occupera moins de place que p allocations de n octets (malloc) Pourquoi ? Realloc Void * realloc (void * pointeur, size_t taille) Permet de modifier la taille d'une zone préalablement allouée Pointeur est l'adresse de début de la zone dont on veut modifier la taille Taille est la taille (totale) souhaitée Renvoie l'adresse de la nouvelle zone ou un pointeur nul si l'allocation a échoué. Si taille est supérieur à l'ancienne, le contenu de celle-ci est conservé (ou recopier à la nouvelle adresse) Si taille inférieur, le contenu reste inchangé