Vous êtes sur la page 1sur 39

Programmation II

Module: M1 - LFSMI - S4

Prof. R. HANNANE
r.hannane@uca.ma

Faculté des Sciences Semlalia, Marrakech


Université Cadi Ayyad

Prof. R. HANNANE (FSSM) Programmation II 1 / 39


Gestion de la mémoire

Gestion de la mémoire

Prof. R. HANNANE (FSSM) Programmation II 2 / 39


Gestion de la mémoire

Gestion de la mémoire
Introduction

La mémoire dans un ordinateur est une succession d’octets (soit


8bits), organisés les uns à la suite des autres et directement
accessibles par une adresse

En C/C++, la mémoire pour stocker des variables est


organisée en deux catégories:
I Allocation automatique via Pile (stack)
I Allocation dynamique via Tas (heap)

Dans la plupart des langages de programmation compilés, la pile


(stack) est l’endroit où sont stockés les paramètres
d’appel et les variables locales des fonctions

Prof. R. HANNANE (FSSM) Programmation II 3 / 39


Gestion de la mémoire

Gestion de la mémoire
Allocation automatique

Lorsque le programme arrive à une ligne comme celle-ci:


int a =8;

Que se passe-t-il ?
1 Le programme demande au système d’exploitation la permission
d’utiliser un peu de mémoire
2 Le système d’exploitation donne l’adresse où il peut stocker
cette variable (c’est lui qui contrôle la mémoire !)
3 Lorsque la fonction est terminée, la variable est
automatiquement supprimée de la mémoire
⇒ Lorsqu’on déclare une variable, le système d’exploitation
était automatiquement appelé par le programme

Prof. R. HANNANE (FSSM) Programmation II 4 / 39


Gestion de la mémoire

Gestion de la mémoire
Allocation automatique

Selon le type de variable que vous demandez de créer


(char,int,double,float...), vous avez besoin de plus ou
moins de mémoire

Un char occupe 1 octet en mémoire, un int occupe


généralement 4 octets. Quant au double, il occupe 8 octets...

Tous ces types ont de l’intérêt si vous créez des


programmes pour de l’informatique embarquée où la
mémoire disponible est plus faible (ex:programmes pour les
téléphones portables, pour les robots, etc)

Prof. R. HANNANE (FSSM) Programmation II 5 / 39


Gestion de la mémoire

Gestion de la mémoire
Allocation automatique

Problème:
Ce n’est pas toujours le cas. Cela dépend des machines

Solution:
On utilise l’opérateur sizeof() qui est une fonctionnalité de
base du langage C. Il faut juste indiquer entre parenthèses le
type que vous voulez analyser

Exemple 1:
printf ( " char : % d octets \ n " , sizeof ( char )); // char : 1 octets
printf ( " int : % d octets \ n " , sizeof ( int )); // int : 4 octets
printf ( " double : % d octets \ n " , sizeof ( double )); // double : 8 octets

Prof. R. HANNANE (FSSM) Programmation II 6 / 39


Gestion de la mémoire

Gestion de la mémoire
Allocation automatique

int a =8;

On voit bien que notre variable a de type int qui vaut 8 occupe
4 octets dans la mémoire
Elle commence à l’adresse 4831836000 (c’est son adresse) et
termine à l’adresse 4831836003
La prochaine variable ne pourra donc être stockée qu’à partir de
l’adresse 4831836004 !
Prof. R. HANNANE (FSSM) Programmation II 7 / 39
Gestion de la mémoire

Gestion de la mémoire
Allocation automatique

Et pour un tableau de type int!


⇒ Chaque ”case” du tableau occupera 4 octets

Si le tableau fait 50 cases, on occupera alors en réalité 4 × 50 = 200


octets en mémoire

int tab [50];

Prof. R. HANNANE (FSSM) Programmation II 8 / 39


Gestion de la mémoire

Gestion de la mémoire
Allocation automatique

Problème:
Même si le tableau est vide, la place en mémoire est
réservée

⇒ Aucun autre programme n’a le droit d’y utiliser cet


emplacement

Solution:
Un des principaux intérêts de l’allocation dynamique est de
permettre à un programme de réserver la place nécessaire
au stockage d’un tableau en mémoire dont il
ne connaissait pas la taille avant la compilation
Prof. R. HANNANE (FSSM) Programmation II 9 / 39
Gestion de la mémoire

Gestion de la mémoire
Allocation dynamique

L’allocation dynamique consiste à réserver manuellement


de l’espace en mémoire pour une variable ou un tableau

Lors de l’allocation dynamique de mémoire, le tas (heap)


est l’autre segment de mémoire utilisé durant l’exécution
d’un programme

La taille du heap est souvent considére comme illimitée


mais elle est en réalité limitée

L’allocation dynamique permet notamment de créer un tableau


dont la taille est déterminée par une variable
au moment de l’exécution
Prof. R. HANNANE (FSSM) Programmation II 10 / 39
Gestion de la mémoire

Allocation dynamique
Les étapes pour l’allocation dynamique
Lors d’une allocation dynamique de mémoire,il faut toujours
suivre ces trois étapes:
1 Appeler une fonction d’allocation pour demander de la
mémoire au système d’exploitation
2 Vérifier la valeur retournée par la fonction d’allocation pour
savoir si le système d’exploitation a bien réussi à allouer la
mémoire
3 Libérer de la mémoire une fois qu’on a fini de l’utiliser
Remarque:
Si on ne libére pas de la mémoire , on s’expose à des fuites de
mémoire, c’est-à-dire que votre programme risque au final de prendre
beaucoup de mémoire alors qu’il n’a en réalité plus besoin de tout cet
espace
Prof. R. HANNANE (FSSM) Programmation II 11 / 39
Gestion de la mémoire

Allocation dynamique
Fonctions d’allocation dynamique

Pour l’allocation dynamique en C, on distingue 4 fonctions :

1 La fonction malloc

2 La fonction calloc

3 La fonction realloc

4 La fonction free
Attention:
On va avoir besoin d’inclure la bibliothèque <stdlib.h>

Prof. R. HANNANE (FSSM) Programmation II 12 / 39


Gestion de la mémoire

Allocation dynamique
La fonction malloc
la fonction malloc permet d’allouer la mémoire sur le tas
Le prototype de la fonction malloc est:
void * malloc ( size_t taille ) ;

L’argument transmis correspond à la taille en octets de la


zone mémoire désirée; c-à-d le nombre d’octets à réserver
La valeur retournée est un pointeur void * sur le premier
octet de la zone mémoire allouée, ou NULL en cas
d’échec de l’allocation
Attention:
La fonction malloc ne sait pas quel type de variable vous
cherchez à créer, c-à-d ne sait pas quel type elle doit retourner,
elle renvoie le type void *
→ Ce sera un pointeur sur n’importe quel type
Prof. R. HANNANE (FSSM) Programmation II 13 / 39
Gestion de la mémoire

Allocation dynamique
La fonction malloc

Exemple 2:
# include < stdlib .h >
int * p = NULL ; // On cr é e un pointeur sur int
p = ( int *) malloc ( sizeof ( int )); /* La fonction malloc inscrit
dans le pointeur p l ’ adresse qui a é t é reserv é e */
...

La fonction malloc a donc renvoyé dans notre pointeur p


l’adresse qui lui a été réservée en mémoire
⇒ Deux possibilités :
Si l’allocation a marché, le pointeur p contient une adresse

Si l’allocation a échoué, le pointeur p contient l’adresse


NULL
Prof. R. HANNANE (FSSM) Programmation II 14 / 39
Gestion de la mémoire

Allocation dynamique
La fonction malloc

Note:
Si l’allocation a échoué, c’est qu’il n’y a plus de mémoire libre. Dans un tel cas,
le mieux est d’arrêter immédiatement le programme parce qu’il ne pourra pas
continuer convenablement
⇒ La fonction standard qu’on peut utilier pour arrêter immédiatement le programme
est :exit(). Elle prend un paramètre : la valeur que le programme doit retourner
exit (0) ;

Exemple 3:
# include < stdlib .h >
int main (){
int * p = NULL ;
p = ( int *) malloc ( sizeof ( int ));
if ( p == NULL ){ // Si l ’ allocation a é chou é
exit (0); // On arr ^ e te imm é diatement le programme
} // On peut continuer le programme normalement sinon
...
return 0;
}

Prof. R. HANNANE (FSSM) Programmation II 15 / 39


Gestion de la mémoire

Allocation dynamique
La fonction malloc
L’exemple suivant définit un pointeur p sur un objet ∗p de type int,
et affecte à ∗p la valeur de la variable i.
Exemple 4:
# include < stdio .h >
# include < stdlib .h >
int main (){
int i = 3;
int * p = NULL ;
printf ( " valeur de p avant initia lisatio n = % ld \ n " ,p );
p = ( int *) malloc ( sizeof ( int ));
printf ( " valeur de p apres initia lisatio n = % ld \ n " ,p );
*p = i;
printf ( " valeur de * p = % d \ n " ,* p );
return 0;
}
/* Affichage :
valeur de p avant init ialisat ion = 0
valeur de p apres init ialisat ion = 5368711424
valeur de * p = 3
*/

Prof. R. HANNANE (FSSM) Programmation II 16 / 39


Gestion de la mémoire

Allocation dynamique
La fonction malloc
Avant l’allocation dynamique, on se trouve dans la configuration
(a)

A ce stade, ∗p n’a aucun sens. En particulier, toute


manipulation de la variable ∗p générerait une violation mémoire,
détectable à l’exécution par le message d’erreur Segmentation
fault
Prof. R. HANNANE (FSSM) Programmation II 17 / 39
Gestion de la mémoire

Allocation dynamique
La fonction malloc
L’allocation dynamique a pour résultat d’attribuer une
valeur à p et de réserver à cette adresse un espace
-mémoire composé de 4 octets pour stocker la valeur de ∗p
(b)

∗p est maintenant définie mais sa valeur n’est pas


initialisée. Cela signifie que ∗p peut valoir n’importe quel entier
(celui qui se trouvait précédemment à cette adresse)
Prof. R. HANNANE (FSSM) Programmation II 18 / 39
Gestion de la mémoire

Allocation dynamique
La fonction malloc

L’affectation ∗p = i; a enfin pour résultat d’affecter à ∗p


la valeur de i. A la fin du programme, on a donc

(c)

Prof. R. HANNANE (FSSM) Programmation II 19 / 39


Gestion de la mémoire

Allocation dynamique
La fonction malloc
Il est important de comparer le programme précédent
qui correspond à la
Exemple 5: situation
...
int i = 3; ⇒
int * p ;
p = ( int *) malloc ( sizeof ( int ));
*p=i;
...

avec celui ci :
qui correspond à la
Exemple 6: situation
...
int i = 3; ⇒
int * p ;
p =& i ;
...

Prof. R. HANNANE (FSSM) Programmation II 20 / 39


Gestion de la mémoire

Allocation dynamique
La fonction malloc

Attention:
Dans le dernier programme, les variables i et ∗p sont
identiques (elles ont la même adresse) ce qui implique que
toute modification de l’une modifie l’autre

Ceci n’était pas vrai dans le premier exemple où ∗p et i avaient


la même valeur mais des adresses différentes

On remarquera que le dernier programme ne nécessite pas


d’allocation dynamique puisque l’espace-mémoire à
l’adresse &i est déjà réservé pour un entier

Prof. R. HANNANE (FSSM) Programmation II 21 / 39


Gestion de la mémoire

Allocation dynamique
La fonction malloc

La fonction malloc permet également d’allouer un espace


pour plusieurs objets contigus en mémoire

On peut écrire par exemple:


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

On a ainsi réservé, à l’adresse donnée par la valeur de p, 8 octets


en mémoire, qui permettent de stocker 2 objets de type int

Prof. R. HANNANE (FSSM) Programmation II 22 / 39


Gestion de la mémoire

Allocation dynamique
La fonction malloc
Exemple 7:
# include < stdio .h >
# include < stdlib .h >
int main (){
int i = 3;
int j = 6;
int * p ;
p = ( int *) malloc (2 * sizeof ( int ));
*p = i;
*( p + 1) = j ;
printf ( " p = % ld \ n * p = % d \ n p +1 = % ld
\ n *( p +1) = % d \ n " ,p ,* p , p +1 ,*( p +1));
return 0;
}
/* Affichage :
p = 5368711424
*p = 3
p +1 = 5368711428
*( p +1) = 6
*/

Prof. R. HANNANE (FSSM) Programmation II 23 / 39


Gestion de la mémoire

Allocation dynamique
La fonction calloc

La fonction calloc() a le même rôle que malloc(). Elle permet


d’allouer de la mémoire

La différence entre les fonctions calloc() et malloc() ???


⇒ c’est que calloc() initialise à 0 tous les éléments de la
zone mémoire

Son prototype est:


void * calloc ( size_t num_elements , size_t size );

num elements est le nombre d’éléments qu’on souhaite


pouvoir stocker en mémoire
size est la taille de ces éléments que l’on obtient avec
l’opérateur sizeof()
Prof. R. HANNANE (FSSM) Programmation II 24 / 39
Gestion de la mémoire

Allocation dynamique
La fonction calloc

Ainsi, si p est de type int *, l’instruction


p = ( int *) calloc (N , sizeof ( int ));

est strictement équivalente à


p = ( int *) malloc ( N * sizeof ( int ));
for ( i = 0; i < N ; i ++)
*( p + i ) = 0;

Remarque:
L’emploi de calloc() est simplement plus rapide

Prof. R. HANNANE (FSSM) Programmation II 25 / 39


Gestion de la mémoire

Allocation dynamique
La fonction calloc

Exemple 8:
# include < stdio .h >
# include < stdlib .h >
int main (){
int nbr =5;
int * np = ( int *) malloc ( nbr * sizeof ( int )); /* Ici , on ne conna ı
^t
pas la valeur des cases m é moires . La valeur de
chacune des cases m é moires est totalement al é atoire . */
int i ;
if ( np == NULL )
{ /* On v é rifie que le syst è me n ’a pas renvoy é un pointeur nul . */
printf ( " ERREUR : probl è me de memoire . " );
exit (0);
}
for ( i = 0; i < nbr ; i ++)
np [ i ] = 0; /* On met chacune des cases à 0. */
/* suite du programme */
return 0;
}

Prof. R. HANNANE (FSSM) Programmation II 26 / 39


Gestion de la mémoire

Allocation dynamique
La fonction calloc

Exemple 9:
# include < stdio .h >
# include < stdlib .h >
int main (){
int nbr =5;
int * np = ( int *) calloc ( nbr , sizeof ( int ));
/* Ici , on conna ı ^ t que les 5 cases m é moires contiennent 0. */
int i ;
if ( np == NULL )
{ /* On v é rifie que le syst è me n ’a pas renvoy é un pointeur nul . */
printf ( " ERREUR : probl è me de memoire . " );
exit (0);
}
/* suite du programme */
return 0;
}

Prof. R. HANNANE (FSSM) Programmation II 27 / 39


Gestion de la mémoire

Allocation dynamique
La fonction realloc

La fonction realloc() sert à ré-attribuer de la mémoire à un


pointeur mais pour une taille mémoire différente

⇒ Elle permet de modifier la taille d’une


zone préalablement allouée (par malloc, calloc ou realloc
elle-même)

On peut aussi la rappeler plusieurs fois de suite (dans une boucle


for ou while par exemple)

Prof. R. HANNANE (FSSM) Programmation II 28 / 39


Gestion de la mémoire

Allocation dynamique
La fonction realloc

Le prototype de realloc() :
void * realloc ( void * ptr , size_t size );

Le premier argument est le pointeur sur lequel on désire


effectuer l’opération,
Le deuxième argument est la taille de l’espace mémoire
qu’on veut allouer

Elle renvoie l’adresse de la nouvelle zone mémoire allouée


soit par malloc(), soit par calloc() (la fonction utilisée avant
l’appel de realloc()), soit par realloc() elle-même

Prof. R. HANNANE (FSSM) Programmation II 29 / 39


Gestion de la mémoire

Allocation dynamique
La fonction realloc

Note:
Si la zone mémoire précédemment allouée peut être
augmentée sans empiéter sur une zone mémoire utilisée
pour autre chose,
⇒ alors l’adresse mémoire renvoyée n’est pas modifiée (c’est la
même que l’ancienne) mais le nombre de cases mémoires
disponibles est modifié

Si en augmentant la zone mémoire initiale on


déborde sur une zone mémoire déjà occupée,
⇒ alors, le système d’exploitation cherchera
une autre adresse pour laquelle le nombre de cases
mémoire nécessaires est disponible
Prof. R. HANNANE (FSSM) Programmation II 30 / 39
Gestion de la mémoire

Allocation dynamique
La fonction realloc

Remarque:
La fonction realloc() ne fait qu’un changement de taille

Elle réalloue le bloc mémoire tout en gardant le contenu


de ce qui se trouvait dans le bloc précédent

Lorsque la nouvelle taille demandée est supérieure à


l’ancienne, le contenu de l’ancienne zone est conservé

Dans le cas où la nouvelle taille est inférieure à l’ancienne,


le début de l’ancienne zone verra son contenu inchangé

Ceci est donc utile pour un tableau dynamique : on peut


ajouter ou enlever une case à la fin du tableau sans le modifier
Prof. R. HANNANE (FSSM) Programmation II 31 / 39
Gestion de la mémoire

Allocation dynamique
La fonction realloc

Exemple 10:
# include < stdio .h >
# include < stdlib .h >
int main ()
{
char * maChaine = ( char *) calloc (15 , sizeof ( char ));
if ( maChaine == NULL ){
printf ( " ERREUR : probl è me de memoire . " );
exit (0);
}

maChaine = realloc ( maChaine , 20 * sizeof ( char ));


if ( maChaine == NULL ){
printf ( " ERREUR : probl è me de memoire . " );
exit (0);
}
/* suite du programme */
return 0;
}
Prof. R. HANNANE (FSSM) Programmation II 32 / 39
Gestion de la mémoire

Allocation dynamique
La fonction free

Enfin, lorsque l’on n’a plus besoin de l’espace-mémoire


alloué dynamiquement (c’est-à-dire quand on n’utilise plus le
pointeur p), il faut libérer cette place en mémoire
Ceci se fait à l’aide de l’instruction free qui a pour syntaxe
void free ( void * nom - du - pointeur );

La fonction free a besoin de l’adresse mémoire à libérer


⇒ On va donc lui envoyer notre pointeur,
Remarque:
A toute instruction de type malloc ou calloc
doit être associée une instruction de type free

Prof. R. HANNANE (FSSM) Programmation II 33 / 39


Gestion de la mémoire

Allocation dynamique
La fonction free

Exemple 11:
# include < stdlib .h >
# include < stdio .h >
int main ()
{
int * p = NULL ;

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


if ( p == NULL ) // On v é rifie si la m é moire a é t é allou é e
{
exit (0); // Erreur : on arr ^ e te tout !
}

// On peut utiliser ici la m é moire


...
free ( p ); // On n ’a plus besoin de la m é moire , on la lib è re
return 0;
}

Prof. R. HANNANE (FSSM) Programmation II 34 / 39


Gestion de la mémoire

Allocation dynamique
Allocation dynamique et tableaux
Remarque:
Généralement, on ne se sert pas de l’allocation dynamique pour
créer une petite variable. On utilise la méthode automatique qui est
plus simple
L’allocation dynamique se sert pour créer un tableau dont
on ne connaı̂t pas la taille avant l’exécution du programme

Note:
Il est interdit en C de créer un tableau en indiquant sa taille à l’aide
d’une variable : int tab [ nbr ];
Ce code fonctionne sur certains compilateurs mais uniquement dans des
cas précis,
⇒ il est recommandé de ne pas l’utiliser !

Prof. R. HANNANE (FSSM) Programmation II 35 / 39


Gestion de la mémoire

Allocation dynamique
Allocation dynamique et tableaux

Avantage de l’allocation dynamique:


L’allocation dynamique permet de créer un tableau qui a
exactement la taille de la variable nbr

Cela grâce à un code qui fonctionnera partout

⇒ On va demander au malloc de nous réserver


nbr * sizeof(int) octets en mémoire :

int * tab = ( int *) malloc ( nbr * sizeof ( int ));

Prof. R. HANNANE (FSSM) Programmation II 36 / 39


Gestion de la mémoire

Allocation dynamique
Allocation dynamique et tableaux

Ainsi, pour créer un tableau d’entiers à n éléments où n est une


variable du programme, on écrit
Exemple 12:
# include < stdlib .h >
int main ()
{ int n ;
int * tab ;
...
tab = ( int *) malloc ( n * sizeof ( int ));
...
free ( tab );
return 0;}

Si on veut en plus que tous les éléments du tableau tab soient


initialisés à zéro, on remplace l’allocation dynamique avec malloc
par tab = ( int *) calloc (n , sizeof ( int ));

Prof. R. HANNANE (FSSM) Programmation II 37 / 39


Gestion de la mémoire

Allocation dynamique
Allocation dynamique et tableaux
Exemple Applicatif:
# include < stdio .h >
# include < stdlib .h >
int main (){
int * tab ;
int i , n ;
n =5;
tab = ( int *) calloc (n , sizeof ( int ));
if ( tab == NULL ) {
printf ( " M é moire non allou é e .\ n " );
exit (0);
}
printf ( " M é moire allou é e avec succ è s avec malloc \ n " );
for ( i =0 ; i < n ; i ++){
*( tab + i )= i ; // *( tab + i ) ou tab [ i ]
}
printf ( " Les é l é ments du tableau sont : \ n " );
for ( i =0 ; i < n ; i ++)
printf ( " %d , " , *( tab + i ));
n =10; // nouvelle taille
tab = realloc ( tab , n * sizeof ( int ));
for ( i =5 ; i < n ; i ++)
*( tab + i )= i ;
printf ( " Les é l é ments du tableau apr è s la r é allocation sont : \ n " );
for ( i =0 ; i < n ; i ++)
printf ( " %d , " , *( tab + i ));
free ( tab ); // liberer l ’ espace reserv é par tab
return 0;
} /* Affichage :
M é moire allou é e avec succ è s avec malloc
Les é l é ments du tableau sont : 0 , 1 , 2 , 3 , 4 ,
Les é l é ments du tableau apr è s la " r é allocation " sont : 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 */

Prof. R. HANNANE (FSSM) Programmation II 38 / 39


Gestion de la mémoire

Gestion de la mémoire
Récapitulatif

Lorsqu’une variable est déclarée à l’aide d’un type de données de


base, le compilateur alloue automatiquement de l’espace
mémoire pour la variable et ceci dans une zone de mémoire RAM
appelée Pile (Stack)
Lorsque le compilateur alloue ou libére manuellement de
l’espace mémoire en fonction des besoins de programmation, on
parle d’allocation dynamique. La mémoire dynamique est gérée
dans la zone de la mémoire RAM appelée Tas (heap)
Pour allouer dynamiquement de la mémoire, le langage C
propose d’utiliser les fonctions suivantes:
I malloc() I realloc()
I calloc() I free()
Prof. R. HANNANE (FSSM) Programmation II 39 / 39

Vous aimerez peut-être aussi