0% ont trouvé ce document utile (0 vote)
17 vues18 pages

Comprendre l'Allocation Dynamique en C

Transféré par

gexek69390
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
17 vues18 pages

Comprendre l'Allocation Dynamique en C

Transféré par

gexek69390
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

Allocation Dynamique

Allocation Dynamique

L. Mounier

UGA - M2 CCI - PL1

8 novembre 2023

1 / 18
Allocation Dynamique

Rappels sur les principaux points abordés en C

Types
types prédéfinis : entiers (dont booléens et caractères), réels
constructeurs de types :
types énumérés, structures (produit de types)
tableaux (statiques), pointeurs

Fonctions et “procédures”
paramètres (donnée et résultat)
portée et durée de vie des données

→ Utilisation de données statiques :


,→ taille, adresse mémoire et durée de vie fixées à la compilation
Allocation dynamique :
,→ gestion à l’exécution de la mémoire utilisée . . .

2 / 18
Allocation Dynamique

Organisation (simplifiée) de la mémoire

Programme à l’exécution ⇒ 3 zones mémoires distinctes

code pile tas


libre

le code : inst. du programme (en langage machine), taille fixe


la pile (stack) : variables locales et paramètres
,→ varie à chaque appels/retours de fonctions
le tas (heap) : dédié aux allocations dynamiques
,→ varie sur appels (implicite/explicite) de primitives systèmes

3 / 18
Allocation Dynamique

Bref rappel sur les pointeurs en C . . .


Constructeur de type “pointeur sur un type T” (noté T*)
représente l’adresse (mémoire) d’un élément de type T
deux opérateurs associés :
déréférencement (*) = accès à l’élément “pointé”
p pointeur sur T ⇒ *p est une valeur de type T
addresse (&) = accès à l’adresse d’une variable
x variable de type T ⇒ &x est de type pointeur sur T
int a, b ; // variables entieres
int *p, *q ; // variables de type pointeur sur entier
int T[10] ; // tableau de 10 entiers
p = &a ; // p pointe sur la variable a
*p = 5 ; // affecte la valeur 5 a la variable a
q = p ; // p pointe egalement sur la variable a
b = *q // affecte 5 à la variable b
p = T ; // p pointe sur T[0]

4 / 18
Allocation Dynamique

Bref rappel sur les pointeurs en C . . .


Constructeur de type “pointeur sur un type T” (noté T*)
représente l’adresse (mémoire) d’un élément de type T
deux opérateurs associés :
déréférencement (*) = accès à l’élément “pointé”
p pointeur sur T ⇒ *p est une valeur de type T
addresse (&) = accès à l’adresse d’une variable
x variable de type T ⇒ &x est de type pointeur sur T
int a, b ; // variables entieres
int *p, *q ; // variables de type pointeur sur entier
int T[10] ; // tableau de 10 entiers
p = &a ; // p pointe sur la variable a
*p = 5 ; // affecte la valeur 5 a la variable a
q = p ; // p pointe egalement sur la variable a
b = *q // affecte 5 à la variable b
p = T ; // p pointe sur T[0]

5 / 18
Allocation Dynamique

Primitives d’allocation dynamique en C


Allocation d’une zone en mémoire
(void *) malloc (int t)
alloue (dans le tas) un bloc mémoire de taille t et renvoie un
pointeur sur ce bloc ; renvoie NULL si l’allocation échoue
la fonction sizeof() renvoie la taille (en octet) d’un type ou
d’une variable

Libération d’une zone en mémoire


void free (void *p)
libère le bloc mémoire pointée par p
comportement indéfini si p ne pointe pas sur un bloc alloué

Ces primitives sont fournies par la librairie <stdlib.h>


(voir également man malloc). 6 / 18
Allocation Dynamique

Primitives d’allocation dynamique en C


Allocation d’une zone en mémoire
(void *) malloc (int t)
alloue (dans le tas) un bloc mémoire de taille t et renvoie un
pointeur sur ce bloc ; renvoie NULL si l’allocation échoue
la fonction sizeof() renvoie la taille (en octet) d’un type ou
d’une variable

Libération d’une zone en mémoire


void free (void *p)
libère le bloc mémoire pointée par p
comportement indéfini si p ne pointe pas sur un bloc alloué

Ces primitives sont fournies par la librairie <stdlib.h>


(voir également man malloc). 7 / 18
Allocation Dynamique

Exemple 1

void f(){
int *p, *q ;
*p = 12 ; // ERREUR : p contient pas une @ memoire valide
p = (int *) malloc(sizeof (int)) ; // conversion de type
*p = 12 ; // OK
q = p ; // p et q pointent sur le meme bloc
free (q) ; // liberation du bloc pointe par p et q
}

int main(){
f() ;
return 0 ;
}

8 / 18
Allocation Dynamique

Exemple 2
Durée de vie d’un bloc alloué dans le tas

(char *) g() { // renvoie un pointeur sur char


char *p ;
p = (char *) malloc(sizeof (char)) ; // conversion de type
return p ; // le bloc pointe par p RESTE ALLOUE
}

int main(){
int *q ;
q = g() ;
*q = ’A’ ; // q contient une @ memoire valide
free (q) ; // liberation du bloc alloue par g()
return 0 ;
}

9 / 18
Allocation Dynamique

Exemple 3
Durée de vie des variables locales

(char *) g() { // renvoie un pointeur sur char


char *p ;
char c ; // variable locale
p = &c ; // OK, p contient l’adresse de c
return p ; // PB, renvoie une @ qui va etre INVALIDE
}

int main(){
int *q ;
q = g() ;
*q = ’A’ ; // q contient une @ memoire INVALIDE
return 0 ;
}

10 / 18
Allocation Dynamique

Application 1 : tableaux dynamique


La fonction malloc() permet de choisir la taille du bloc à allouer
→ tableaux dynamiques ...
Exemple
int *t ;

/* allocation d’un bloc de taille 10 entiers


t = (int *) malloc (10*sizeof(int)) ;

/* acces indexe possible */


t[0] = 4 ;
t[8] = 5 ;
free(t) ;

Variante : fonction calloc()


t = (int *) calloc (10,sizeof(int)); // alloue un bloc de 10 int
11 / 18
Allocation Dynamique

Application 2 : séquences chaı̂nées

Représentation d’une séquence S en langage C ?


1 tableaux statiques :
taille mémoire et durée de vie S fixée à la compilation
aucun surcoût à l’exécution

2 tableaux dynamique :
taille mémoire maximale de S fixée à l’allocation
durée de vie de S peut varier à l’exécution
(léger) surcoût à l’exécution (1 appel à allouer/libérer)

comment adapter dynamiquement la taille mémoire de S ?


(en fonction des insertions/suppressions d’éléments)
→ séquences chaı̂nées !

12 / 18
Allocation Dynamique

Séquences chaı̂nées en C

Notation algorithmique
Cellule : un type
Cellule : le type <elem: un entier, suiv: pointeur sur Cellule>
Seq : le type pointeur sur Cellule

Implémentation en C
typedef struct cellule {
int elem ;
struct cellule *suiv ;
} Cellule ;

typedef Cellule *Seq ;

Le pointeur NULL représente la séquence vide

13 / 18
Allocation Dynamique

Séquences chaı̂nées en C

Notation algorithmique
Cellule : un type
Cellule : le type <elem: un entier, suiv: pointeur sur Cellule>
Seq : le type pointeur sur Cellule

Implémentation en C
typedef struct cellule {
int elem ;
struct cellule *suiv ;
} Cellule ;

typedef Cellule *Seq ;

Le pointeur NULL représente la séquence vide

14 / 18
Allocation Dynamique

Parcours d’une séquence chaı̂née


Incrémenter tous les éléments de la séquence S ?

void IncElements (Seq S) {


Seq elemC ; // element courant pour le parcours

elemC = S ;
while (elemC != NULL) { // tant qu’il existe encore un element
elemC->elem = elemC->elem + 1 ; // on l’incremente
elemC = elemC->suiv ; // on passe au suivant
}
}

Le paramètre S est ici de type Seq car il n’est pas modifié


(passage par donnée)
Par contre chaque élément de S est modifié . . .
15 / 18
Allocation Dynamique

Insertion en tête dans une séquence chaı̂née (1)

Version 1 : fonction
Seq InsTete (Seq S, int x)
ajoute le nouvel élément x en tête de S et renvoie la nouvelle
séquence
Seq InsTete (Seq S, int x) {
Seq tmp ; // temporaire pour le nouvel element

// allocation d’un nouvel element x


tmp = (Seq) malloc (sizeof(Cellule)) ;
tmp->elem = x ;
tmp->suiv = S ; // chainage en tete de S
return tmp ; // renvoie la nouvelle sequence
}

16 / 18
Allocation Dynamique

Insertion en tête dans une séquence chaı̂née (2)


Version 2 : action avec paramètre résultat
void InsTete (Seq *S, int x)
modifie S en lui ajoutant en tête un nouvel élément x
void InsTete (Seq *S, int x) {
Seq tmp ; // temporaire pour le nouvel element

// allocation d’un nouvel element x


tmp = (Seq) malloc (sizeof(Cellule)) ;
tmp->elem = x ;
tmp->suiv = *S ; // chainage en tete de S
*S = tmp ; // affecte a S ce nouveau (premier) element
}

Le paramètre S est ici de type Seq * car il va être modifié


(passage par donnée-résultat)
17 / 18
Allocation Dynamique

Et dans d’autres langages ?


Allocation dynamique présente dans la plupart des langage de
programmation, mais sous différentes formes . . .
C, C++
gestion mémoire entièrement à la charge du programmeur
risque important d’erreurs
surcoût réduit (en temps d’exécution, en mémoire utilisée)
Java
gestion mémoire partiellement à la charge du programmeur
libération “automatique” (ramasse-miettes)
peu de risque d’erreurs
surcoût possible (en temps d’exécution, en mémoire utilisée)
JavaScript, Python
gestion mémoire implicite (allocation, libération)
peu de risque d’erreurs
surcoût (en temps d’exécution, en mémoire utilisée)
18 / 18

Vous aimerez peut-être aussi