0% ont trouvé ce document utile (0 vote)
81 vues31 pages

Gestion Dynamique

Transféré par

bentaherdaly123
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 PPSX, PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
81 vues31 pages

Gestion Dynamique

Transféré par

bentaherdaly123
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 PPSX, PDF, TXT ou lisez en ligne sur Scribd

La gestion dynamique de la mémoire

Les pointeurs 2

Présentation de la problématique

 Problématique
Reprenons la problématique de la location d’une maison et sa projection sur le mécanisme de gestion de la mémoire

La Maison ⇔ L’espace mémoire où la variable sera stockée


(Adresse)

L’agence ⇔ Le système d’exploitation qui va gérer la mémoire

La ville ⇔ La mémoire (RAM)

La personne ⇔ La variable qu’on veut stocker


Les pointeurs 3

Présentation de la problématique

 Problématique
Reprenons la problématique de la location d’une maison et sa projection sur le mécanisme de gestion de la mémoire

L’agence immobilière va gérer les disponibilités en fonction des besoins du demandeur.

Si le demandeur est seul pendant sa période de résidence,


 il est probable qu'un studio ou un appartement à une chambre suffise.

Si le demandeur a une famille de 3 ou 4 personnes,


 l'agence devra trouver une maison avec un espace plus grand, comprenant 3 ou 4 chambres

De manière similaire, le système d'exploitation gère la mémoire d'un ordinateur,


Il alloue de l'espace mémoire en fonction des besoins des programmes en cours d'exécution.
La gestion dynamique de la mémoire 4

1) Introduction

 Contrairement à la mémoire statique, où la taille et la portée de la mémoire sont définies à la compilation

 La gestion dynamique de la mémoire offre une plus grande flexibilité de l’utilisation de la mémoire

 Elle consiste à demander au système d'exploitation de nous allouer ou libérer un espace d'une taille donnée dans la mémoire

pendant l'exécution du programme.

 Le langage C offre plusieurs outils pour effectuer ce type d’opérations.


La gestion dynamique de la mémoire 5

2) Allocation de mémoire

► Définition

 Pour allouer une zone mémoire dynamiquement en C, on utilisera la fonction malloc.

 La fonction malloc alloue de l'espace mémoire en fonction du type (pointeur, objet,...) et la taille demandés.

 Elle retourne un pointeur générique donnant l'adresse de début du bloc alloué.

 Sinon, elle retourne un pointeur NULL si l'allocation a échoué pour une insuffisance d'espace.

 L’utilisation de cette fonction nécessite l’appelle des bibliothèques « stdlib.h ».


La gestion dynamique de la mémoire 6

2) Allocation de mémoire

► Allocation des objets isolés

 Syntaxe :

type* NomPointeur = (type*) malloc (taille_bloc) ; // type* NomPointeur = (type*) malloc ( sizeof (type) ) ;

 Exemple :

int * p; // définit un pointeur vers un entier

p = (int *) malloc (sizeof (int) ) ; //alloue de l'espace pour un entier et affecte l'adresse de cet espace (à p).

*p=1; // écrit 1 dans la zone mémoire allouée

p mémoire
0XAABC
1
La gestion dynamique de la mémoire 7

2) Allocation de mémoire

► Allocation des objets isolés

 Remarque :

En C, il n'est pas possible de faire l’allocation et l’initialisation à la fois en utilisant la syntaxe suivante :
error: lvalue required as left operand of assignment
int *p = (int *) malloc (sizeof (int) ) = 1

L’expression (int *) malloc (sizeof (int) ) ne peut pas apparaître à gauche d'une affectation.
Comme avec l’expression 5 = x; où le compilateur générera ce type d’erreur

 Solution ?

Vous devez d'abord allouer la mémoire dynamiquement à l'aide de malloc() puis attribuer les valeurs individuellement à chaque

élément du bloc de mémoire.


La gestion dynamique de la mémoire 8

2) Allocation de mémoire

► Allocation des tableaux (unidimentionnel)

 Syntaxe :

type* nomPointeur = (type*) malloc (nb_blocs * taille_bloc) ; // type* nomPointeur = (type*) malloc (nb_blocs * sizeof (type) ) ;

Avec :

type* : permet de spécifier le type du pointeur.

nomPointeur : permet de spécifier le nom du pointeur.

nb_blocs : permet de spécifier le nombre d’éléments à allouer

taille_bloc : permet de spécifier la taille du bloc (en octets) de mémoire à allouer.

sizeof(type) est utilisé pour obtenir la taille en octets du type de données type. Cela garantit que l'allocation de

mémoire est correctement dimensionnée en fonction du type de données (char, int, etc).
La gestion dynamique de la mémoire 9

2) Allocation de mémoire

► Allocation des tableaux (unidimensionnel)

 Exemples d’allocation :

1) Allocation d’un tableau d’entiers

int * t ;// définir un pointeur vers un entier

t = (int *) malloc (10*sizeof (int) ) ; //allouer de l'espace pour un tableau d’entiers de taille 10 (int t[10]).

2) Allocation d’une chaine de caractères

char * ch; // définit un pointeur vers un char

ch = (char *) malloc (10*sizeof (char) ) ; //alloue de l'espace pour une chaine de caractère de taille 10 (c[10]).
La gestion dynamique de la mémoire 10

2) Allocation de mémoire

► Initialisation des tableaux (unidimensionnel)

 Exemple 1 (initialisation d’un tableau d’entiers):

il n'est pas possible d'initialiser un tableau alloué


int * t ;
dynamiquement en utilisant cette syntaxe
t = (int *) malloc (10*sizeof (int) ) ;
Explication de l'erreur:
*t={1,2,3,4,5,6,7,8,9,10} *t est un pointeur vers un entier, donc il ne peut stocker
for (int i=0 ; i <10 ; i++){ qu'une seule valeur entière.
*(t+i) = i+1 ; } {1,2,3,4,5,6,7,8,9,10} est une liste d'initialisation qui contient
10 valeurs.

t
0XAA15

mémoire 1 2 3 4 5 6 7 8 9 10
La gestion dynamique de la mémoire 11

2) Allocation de mémoire

► Initialisation des tableaux (unidimensionnel)

 Exemple 2 (initialisation d’une chaine de caractères):

char * ch;
Cette méthode d’initialisation n'est pas recommandée
ch = (char *) malloc (10*sizeof (char) ) ; Elle ne garantit pas toujours que l'espace suffisant sera alloué
pour tenir compte du caractère nul de fin de chaîne (\0)
*ch="Bonjour";
Solution ? Si vous voulez copier une chaîne de caractères dans
strcpy (ch,"Bonjour") ;
une variable pointeur de caractère, vous devez utiliser des
fonctions comme strcpy()

ch
0XAA15

mémoire B O N J O U R \0 0 0
La gestion dynamique de la mémoire 12

2) Allocation de mémoire

► Allocation des tableaux (multidimentionnel)

Pour la création d’un tableau à deux dimensions de L lignes et C colonnes, l'idée consiste à créer L vecteurs comportant chacun C éléments.

 Le schéma suivant montre la représentation en mémoire de la structure dynamique à créer :

L'accès à un élément d'indice (i,j) se fait comme suit :


*(*(M+i)+j) ⇔ M[i][j]
La gestion dynamique de la mémoire 13

2) Allocation de mémoire

► Allocation des tableaux (multidimentionnel)

 Syntaxe :

type** Pointeur = (type**) malloc (nb_blocs * taille_bloc) ; // type** Pointeur= (type**) malloc (nb_blocs *sizeof (type*) ) ;

 Exemple :

int L =5 , C=5 ; // L = nombre de lignes et C = nombre de colonnes

int** M ; // déclaration d’un tableau de pointeurs nommé M

M = (int**) malloc (L * sizeof(int*)); // allouer de l'espace pour un tableau de pointeurs de taille L (5)

for(int i=0 ; i<L ; i++) {

*(M+i)= (int *) malloc (C * sizeof (int) ) ; // allouer de l'espace associé au pointeur M+i qui pointe sur un tableau de valeurs de taille C (5)

}
La gestion dynamique de la mémoire 14

2) Allocation de mémoire

► Utilisation de calloc

 C offre également une fonction qui joue le même rôle que celui de malloc.

 Il s’agit de la fonction calloc qui permet d’allouer un bloc de mémoire en initialisant tous ces octets à la valeur 0.

 Elle retourne un pointeur sur l'espace alloué si l'allocation s'est bien déroulée.

 Sinon, elle retourne un pointeur NULL si l'allocation a échoué.

 Les points de différence avec malloc ?

 L'initialisation : calloc met tous les octets du bloc à la valeur 0 alors que malloc ne modifie pas la zone de mémoire.

 Les paramètres : calloc requière deux paramètres (le nombre d'éléments consécutifs à allouer et la taille d'un élément) alors que

malloc attend la taille totale du bloc à allouer.


La gestion dynamique de la mémoire 15

2) Allocation de mémoire

► Utilisation de calloc

 Syntaxe :

type* nomPointeur = (type*) calloc (nb_blocs, taille_bloc) // type* nomPointeur = (type*) calloc (nb_blocs , sizeof (type) ) ;

 Exemple :

int * p; // définir un pointeur vers un int

int n = 5; //déclarer une variable n égale à 5 (nombre de blocs)

p = (int *) calloc (n , sizeof (int) ) ; //allouer de l'espace pour 5 entiers.

for (int i=0; i<n;i++) {


Résultat : le programme affiche 0 0 0 0 0
printf("%d ", *(p+i) ); puisque calloc initialise les valeurs à 0.

}
La gestion dynamique de la mémoire 16

3) Réallocation de mémoire

► Définition

 C offre une fonction (realloc) qui permet de modifier la taille d'une zone préalablement allouée (par malloc, calloc ou realloc).

 Elle permet de réallouer un bloc de mémoire.

 En cas de succès, cette fonction retourne un pointeur sur la zone réallouée.

 Sinon, elle retourne un pointeur NULL si la réallocation a échoué.


La gestion dynamique de la mémoire 17

3) Réallocation de mémoire

► Définition

 Stratégie de réallocation ?

 Si l'espace mémoire libre qui suit le bloc à réallouer est suffisamment grand, le bloc de mémoire est simplement agrandi

/// /// /// /// /// /// ///

Espace alloué déjà Espace libre Nouvel espace alloué

 Si l'espace libre n'est pas suffisant, un nouveau bloc de mémoire sera alloué.

 Le contenu de la zone d'origine sera recopié dans la nouvelle zone et le bloc mémoire d'origine sera libéré automatiquement

/// /// /// /// /// /// /// /// ///

Espace alloué déjà Espace non libre Nouvel espace alloué


La gestion dynamique de la mémoire 18

3) Réallocation de mémoire

► Utilisation de realloc

 Syntaxe :

type* PtrBloc = (type*) realloc (PtrBloc, taille_bloc)

// PtrBloc : l’adresse du bloc de mémoire à réallouer , taille_bloc : taille (en octets) du bloc de mémoire à allouer.

 Exemple :

int * p; // définit un pointeur vers un int

int n = 10; //déclarer une variable n égale à 10 (nombre de blocs)

p = (int *) calloc (n, sizeof (int) ) ; //allouer de l'espace pour 10 entiers.

p = (int *) realloc (p, (n+5) * sizeof (int) ) ; //allouer de l'espace pour 5 autres entiers en plus de 10 entiers déjà alloués
La gestion dynamique de la mémoire 19

Exercice d’application

Écrire un programme permettant de:

1) allouer dynamiquement un espace mémoire pour 10 entiers initialisés à 0

2) agrandir le bloc mémoire en allouant de l'espace pour 5 autres entiers initialisés à 1

3) afficher le contenu de ce bloc mémoire (les valeurs des entiers).

Résultat :
0 0 0 0 0 0 0 0 0 0 1 1 1 1 1

19
La gestion dynamique de la mémoire 20

Exercice d’application

► Solution

#include <stdio.h> //Afficher 0000000000 puisque calloc initialise les valeurs à 0.


#include <stdlib.h>
for (i=0; i<n;i++) {
int main(){ printf("%d ", *(p+i) ); }
int *p , i ; printf("\n");
int n = 10 ; // Initialiser le reste des blocs à 1
// Allocation de 10 blocs for ( i=n ; i<n+5 ; i++)
p = (int*) calloc (n , sizeof(int)) ; *(p+i)=1 ;
// Réallocation de mémoire pour 15 blocs //Afficher les valeurs
p = (int*) realloc (p, (n+5) *sizeof(int)) ; for ( i=0 ; i<n+5 ; i++) {
printf("%d ", *(p+i) ); }
return 0 ; }
La gestion dynamique de la mémoire 21

4) Libération de mémoire

► Libération de mémoire

 Pour libérer une zone mémoire dynamiquement en C, on utilise la fonction free.

 La fonction free permet de libérer un espace préalablement alloué.

 Aucune valeur de retour n'est produite.

 L’utilisation de cette fonction nécessite l’appelle des bibliothèques « stdlib.h ».

21
La gestion dynamique de la mémoire 22

6) Problème de fuite de la mémoire

 États de la mémoire suite à l'exécution des instructions


int i; int* p; p = (int *) malloc (sizeof (int) ) ; i=5; *p=6; Fin de l’exécution

p p FF0EA5C p FF0EA5C 6 6
i i i 5

i et p sont deux malloc va engendrer la La valeur 5 est affectée à i et A ce niveau toutes les variables de type auto
variables de type création d'une variable 6 à la zone dynamique seront automatiquement libérées
"auto" dynamique dont l'adresse pointée par p  La portée de i et p dans ce cas est limitée
est stockée dans p au bloc du main
 mais pas la zone dynamique pointée par p

Pour remédier à ce problème, il faut libérer la zone pointée avant de quitter le programme en utilisant free (p)
22
La gestion dynamique de la mémoire 23

4) Libération de mémoire

► Libération de mémoire

Libération d’un objet isolé

 Syntaxe :

free (PtrZone) ; // Le paramètre PtrZone désigne un pointeur qui pointe sur la zone à libérer

 Exemple :

int * p; // définir un pointeur vers un int

p = (int *) malloc (sizeof (int) ) ; //allouer de l'espace pour un entier et affecte l'adresse de cet espace (à p).

*p=1; // écrire 1 dans la zone mémoire allouée

printf(" Le nombre saisi est %d ", *p ); // Afficher le contenu de la zone mémoire allouée (*p)

free (p) ; // Libérer l’objet p

23
La gestion dynamique de la mémoire 24

4) Libération de mémoire

► Libération de mémoire

Libération des tableaux dynamiques (unidimensionnel)

 Syntaxe :

free (PtrZone) ; // Le paramètre PtrZone désigne un pointeur qui pointe sur la zone à libérer

 Exemple :

int * t; // définir un pointeur vers un int

t = (int *) malloc (5* sizeof (int) ) ; //allouer de l'espace pour un tableau de 5 entiers et affecte l'adresse de cet espace (à t).

for (i=0; i<n; i++) {

*(t+i) )=i ; } Initialiser le tableau t par les valeurs du compteur i

free (t) ; // Libérer l’espace alloué par le tableau t

24
La gestion dynamique de la mémoire 25

4) Libération de mémoire

► Libération de mémoire

Libération des tableaux dynamiques (multidimensionnel)

Pour libérer la mémoire allouée pour un tableau multidimensionnel en C, vous devez :

1) Libérer chaque niveau de dimension du tableau séparément, en commençant par les tableaux internes.

2) Remonter jusqu'au tableau principal

 Cela garantit que toute la mémoire allouée pour le tableau est libérée correctement.
La gestion dynamique de la mémoire 26

4) Libération de mémoire

► Libération de mémoire

Libération des tableaux dynamiques (multidimensionnel)

 Exemple : Libérer l’espace mémoire allouée pour une matrice (tableau 2D)

// Libérer l’espace alloué par le tableau M

for (i=0; i<L ; i++) {

free (*(M+i)) ;}

// Libérer l’espace alloué par le tableau M

free (M) ;
La gestion dynamique de la mémoire 27

Exercice d’application

Écrire un programme permettant de remplir et afficher un tableau d'entiers à deux dimensions de taille [3][4] en utilisant les pointeurs.

Solution :

#include <stdio.h> for(i=0; i<L;i++){ // Affichage du tableau M


#include <stdlib.h> for(j=0; j<C;j++){
int main(){ printf("%d | ",*(*(M+i)+j)) ;
int C = 4 ; int L = 3; int **M; int i,j ; }
M = (int**) malloc (L * sizeof(int*)) ; printf("\n ") ;
for(i=0; i<L;i++) // Allocation du tableau M }
*(M+i)= (int *) malloc (C * sizeof (int) ) ; for(i=0;i<L;i++) { // Libérer les tableaux internes
for(i=0; i<L;i++){ // Remplissage du tableau M
for(j=0; j<C;j++){ free (*(M+i)) ;
printf("donner M[%d][%d] : ",i , j); }
scanf ("%d", *(M+i)+j) ;} free (M) ; // Libérer le tableau principal M
} return 0;
}
La gestion dynamique de la mémoire 28

5) Variable auto vs variable dynamique

 Une variable auto est une variable dont la durée de vie est gérée d'une manière automatique par le système.

 Une telle variable est allouée sur la pile (empilée) suite à l'exécution de l'instruction qui la déclare.

 Elle sera ensuite automatiquement libérée (dépilée) lorsque l'exécution du programme atteint la fin du bloc d'instructions dans

lequel elle est déclarée.

 Une variable dynamique est une variable dont la durée de vie est gérée par le programmeur.

 Une telle variable est allouée sur le tas (et non sur la pile) par un appel explicite à malloc.

 Elle ne sera libérée de la mémoire qu'à travers un appel explicite à free ou suite au redémarrage du système.

Question 1 : Quelle est la différence entre tas et pile ?

Question 2 : Quelle est l’utilité de l'allocation dynamique de la mémoire ?


La gestion dynamique de la mémoire 29

5) Variable auto vs variable dynamique

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


Question 1 : Quelle est la différence entre tas et pile ?

 La pile (ou Stack) est utilisé pour l’allocation de mémoire statique. objet
a = 10 a=&
 le tas(ou Heap) est utilisé pour l’allocation de mémoire dynamique
pile pile tas

Question 2 : Quelle est l’utilité de l'allocation dynamique de la mémoire ?

 pour créer des variables dont la taille est inconnue au moment de la compilation.

 Par exemple, lorsqu'il s'agit de créer un tableau dont le nombre d'éléments sera déterminé au moment de l'exécution par l'utilisateur.
La gestion dynamique de la mémoire 30

6) Problème de fuite de la mémoire

 Une zone mémoire dynamiquement créée, mais non explicitement libérée va persister dans la RAM même après la fin de l'exécution.

 Ce phénomène est appelé : fuite de mémoire

 Le programme suivant donne une illustration de ce phénomène :


int main() {  Ce programme se compile avec succès.

int i;  Il s'exécute également d'une manière normale.

i=5;  Toutefois à sa sortie il engendre une fuite de mémoire.

int* p = (int *) malloc (sizeof (int) ) ;


*p=6;
printf("i=%d | *p= %d ",i , *p) ;
return 0 ;
}
Fin du cours

31

Vous aimerez peut-être aussi