Cours C++ Les Memoires

13
Cours Langage C/C++ Mémoire et allocation dynamique Thierry Vaira BTS IRIS Avignon [email protected] v0.1

description

Cours C++ Les Memoires

Transcript of Cours C++ Les Memoires

Page 1: Cours C++ Les Memoires

Cours Langage C/C++Mémoire et allocation dynamique

Thierry Vaira

BTS IRIS Avignon

[email protected] « v0.1

Page 2: Cours C++ Les Memoires

La mémoire

La pile et le tas

La mémoire dans un ordinateur est une succession d’octets (soit 8bits), organisés les uns à la suite des autres et directementaccessibles par une adresse.

En C/C++, la mémoire pour stocker des variables est organisée endeux catégories :

1 la pile (stack)2 le tas (heap)

Remarque : Dans la plupart des langages de programmation compilés,la pile (stack) est l’endroit où sont stockés les paramètres d’appel etles variables locales des fonctions.

tv (BTS IRIS Avignon) Cours C/C++ [email protected] « v0.1 2 / 13

Page 3: Cours C++ Les Memoires

La mémoire

La pile (stack)

La pile (stack) est un espace mémoire réservé au stockage desvariables désallouées automatiquement.

Sa taille est limitée mais on peut la régler (appel POSIX setrlimit).

La pile est bâtie sur le modèle LIFO (Last In First Out) ce qui signifie"Dernier Entré Premier Sorti". Il faut voir cet espace mémoire commeune pile d’assiettes où on a le droit d’empiler/dépiler qu’une seuleassiette à la fois. Par contre on a le droit d’empiler des assiettes detaille différente. Lorsque l’on ajoute des assiettes on les empile par lehaut, les unes au dessus des autres. Quand on les "dépile" on le faiten commençant aussi par le haut, soit par la dernière posée.Lorsqu’une valeur est dépilée elle est effacée de la mémoire.

tv (BTS IRIS Avignon) Cours C/C++ [email protected] « v0.1 3 / 13

Page 4: Cours C++ Les Memoires

La mémoire

Le tas (heap)

Le tas (heap) est l’autre segment de mémoire utilisé lors del’allocation dynamique de mémoire durant l’exécution d’unprogramme informatique.

Sa taille est souvent considére comme illimitée mais elle est en réalitélimitée.

Les fonctions malloc et free, ainsi que les opérateurs du langageC++ new et delete permettent, respectivement, d’allouer etdésallouer la mémoire sur le tas.

La mémoire allouée dans le tas doit être désallouée explicitement.

tv (BTS IRIS Avignon) Cours C/C++ [email protected] « v0.1 4 / 13

Page 5: Cours C++ Les Memoires

La mémoire

Sous Linux, on peut visualiser facilement les valeurs du tas et de la pile :

$ ulimit -a...data seg size (kbytes, -d) unlimited...stack size (kbytes, -s) 8192...

La taille de la pile étant limitée (ici à 8Mo), cela peut provoquer desécrasements de variables et surtout des "Erreur de segmentation" en casde dépassement. Il est évidemment recommandé d’allouer dans le tas les"grosses" variables sous peine de surprise !

tv (BTS IRIS Avignon) Cours C/C++ [email protected] « v0.1 5 / 13

Page 6: Cours C++ Les Memoires

Allocation dynamique

malloc et free

L’allocation d’une nouvelle zone mémoire se fait dans un endroitparticulier de la mémoire appelée le tas (heap).Elle se fait par la fonction malloc : void *malloc(size_ttaille) ;

L’argument transmis correspond à la taille en octets de la zonemémoire désirée.La valeur retournée est un pointeur void * sur la zone mémoireallouée, ou NULL en cas d’échec de l’allocation.Si vous devez redimensionner un espace mémoire qui a été allouédynamiquement, il faudra utiliser la fonction realloc().La mémoire allouée doit, à un moment ou un autre, être libérée.Cette libération mémoire se fait par la procédure free : voidfree(void *pointeur) ;

tv (BTS IRIS Avignon) Cours C/C++ [email protected] « v0.1 6 / 13

Page 7: Cours C++ Les Memoires

Allocation dynamique

Exemple : allocation mémoire

int *p; // pointeur sur un entierint *T; // pointeur sur un entier

// allocation dynamique d’un entierp = (int *)malloc(sizeof(int)); // alloue 4 octets (= int) en mémoire*p = 1; // ecrit 1 dans la zone mémoire allouée

// allocation dynamique d’un tableau de 10 intT = (int *)malloc(sizeof(int) * 10); // alloue 4 * 10 octets en mémoire// initialise le tableau avec des 0 (cf. la fonction memset)for(int i=0;i<10;i++) {

*(T+i) = 0; // les 2 écritures sont possiblesT[i] = 0; // identique à la ligne précèdente

}// ou plus directementmemset(T, 0, sizeof(int)*10); // il faudra alors inclure string.h

free(p);free(T);

Une fois qu’une zone mémoire a été libérée, il ne faut sous aucun prétexte y accéder, demême qu’il ne faut pas tenter de la libérer une seconde fois.

tv (BTS IRIS Avignon) Cours C/C++ [email protected] « v0.1 7 / 13

Page 8: Cours C++ Les Memoires

Allocation dynamique

Règles de bonne conduite

Un certain nombre de règles, quand elles sont observées, permettent de semettre à l’abri de problèmes :

Toute déclaration de pointeur s’accompagne de son initialisation àNULL

Avant tout appel de malloc(), on doit s’assurer que le pointeur àallouer est bien NULL

Après tout appel de malloc(), on s’assure qu’aucune erreur ne s’estproduiteAvant de libérer une zone mémoire, on s’assure que son pointeur n’estpas NULL

Dès qu’une zone mémoire vient d’être libérée par free(), onréinitialise son pointeur à NULL

tv (BTS IRIS Avignon) Cours C/C++ [email protected] « v0.1 8 / 13

Page 9: Cours C++ Les Memoires

Allocation dynamique

new et delete

Pour allouer dynamiquement en C++, on utilisera l’opérateur new.Celui-ci renvoyant une adresse où est crée la variable en question, ilnous faudra un pointeur pour la conserver.Manipuler ce pointeur, reviendra à manipuler la variable allouéedynamiquement.Pour libérer de la mémoire allouée dynamiquement en C++, onutilisera l’opérateur delete.

tv (BTS IRIS Avignon) Cours C/C++ [email protected] « v0.1 9 / 13

Page 10: Cours C++ Les Memoires

Allocation dynamique

Pour allouer dynamiquement en C++, on utilisera l’opérateur new.

Exemple : allocation dynamique

#include <iostream>#include <iostream>#include <new>

using namespace std;

int main (){

int * p1 = new int; // pointeur sur un entier

*p1 = 1; // ecrit 1 dans la zone mémoire allouéecout << *p1 << endl; // lit et affiche le contenu de la zone mémoire allouée

delete p1; // libère la zone mémoire allouée

return 0;}

tv (BTS IRIS Avignon) Cours C/C++ [email protected] « v0.1 10 / 13

Page 11: Cours C++ Les Memoires

Allocation dynamique

Exemple : allocation dynamique d’un tableau

#include <iostream>#include <new>

using namespace std;

int main (){

int * p2 = new int[5]; // alloue un tableau de 5 entiers en mémoire

// initialise le tableau avec des 0 (cf. la fonction memset)for(int i=0;i<5;i++){

*(p2 + i) = 0; // les 2 écritures sont possiblesp2[i] = 0; // identique à la ligne précèdentecout << "p2[" << i << "] = " << p2[i] << endl;

}

delete [] p2; // libère la mémoire allouéereturn 0;

}

tv (BTS IRIS Avignon) Cours C/C++ [email protected] « v0.1 11 / 13

Page 12: Cours C++ Les Memoires

Allocation dynamique

Pour allouer dynamiquement un objet, on utilisera l’opérateur new.

Exemple : allocation dynamique d’un objet

#include <iostream>#include "point.h"using namespace std;

int main(){

Point *pointC; // je suis pointeur sur un objet de type Point

pointC = new Point(2,2); // j’alloue dynamiquement un objet de type Point

pointC->afficher(); // Comme pointC est une adresse, je dois utiliser l’opérateur -> pour accéder auxmembres de cet objet

pointC->setY(0); // je modifie la valeur de l’attribut _y de pointB

(*pointC).afficher(); // cette écriture est possible : je pointe l’objet puis j’appelle sa méthodeafficher()

delete pointC; // ne pas oublier de libérer la mémoire allouée pour cet objet

return 0;}

tv (BTS IRIS Avignon) Cours C/C++ [email protected] « v0.1 12 / 13

Page 13: Cours C++ Les Memoires

Allocation dynamique

Fuite de mémoire

L’allocation dynamique dans le tas ne permet pas la désallocationautomatique.Chaque allocation avec "new" doit impérativement être libérée(détruite) avec "delete" sous peine de créer une fuite de mémoire.La fuite de mémoire est une zone mémoire qui a été allouée dans letas par un programme qui a omis de la désallouer avant de seterminer. Cela rend la zone inaccessible à toute application (y comprisle système d’exploitation) jusqu’au redémarrage du système. Si cephénomène se produit trop fréquemment la mémoire se remplit defuites et le système finit par tomber faute de mémoire.

Ce problème est évité en Java en introduisant le mécanisme de"ramasse-miettes" (Garbage Collector).

tv (BTS IRIS Avignon) Cours C/C++ [email protected] « v0.1 13 / 13