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é