Problèmes de mémoire ?

Petit point sur C++ et la gestion mémoire

Publié dans C / C++ | Marqué avec , , , , ,
Share

Différents types de données

En terme de mémoire, il existe différents types de donnée en C++.

  • Donnée statique : emplacement alloué une fois pour toute la durée du programme
  • Donnée automatique (pile) : emplacement alloué à l’entrée d’un bloc (exemple : une fonction, une boucle, …) et libéré à sa sortie
  • Donnée dynamique (tas) : emplacement alloué et libéré à la demande du programme, donc du développeur à l’aide des opérateurs new et delete Bref à l’aide de pointeurs.

On parle ainsi de trois classes d’allocation : statique, automatique, dynamique.
Dans cet article, nous allons étudier un peu plus en détails l’allocation / destruction de données dynamiques.

Allocation de données dynamiques

// Allocation d'un type quelconque (exemple : int, char, une classe)
type *maVariable = new type;

// Allocation d'un tableau de n éléments de type quelconque (exemple : int, char, une classe)
// Le pointeur retourné pointe sur l'adresse du premier élément du tableau
type *maVariable = new type[n];

Destruction de données dynamiques

La destruction est un tout petit peu plus compliqué puisqu’il y a plus de cas à prendre en compte : emplacement déjà libéré ou non, allocation d’un tableau d’objets ou de types classiques.

Syntaxe usuelle de l’opérateur delete :

delete adresse;

Voyons plus en détails les différents cas :

// Allocation simple
int *monInt = new int;
delete monInt;

// Allocation multiple
int *mesInt = new int[10];
delete[] mesInt;
// "delete mesInt" supprime seulement l'adresse du tableau

// Allocation multiple : pour un tableau d'objet
MonObjet *mesObjets = new MonObjet[10];
delete[] mesObjets;

Il est conseillé de rendre nul un pointeur détruit afin de vérifier son état afin d’éviter les suppressions multiples. Les exemples précédents donneraient plutôt :

if (NULL != monPointeur) {
	delete monPointeur;
	monPointeur = NULL;
}

Quelques mots sur les données automatiques

Un dernier petit détail à propos des données automatiques. Certes tout s’effectue automatiquement pour l’allocation et la destruction, mais il y a création d’une copie des objets :

  • lors du passage en argument : maFunction(instanceDeMonObjet)
  • lors d’une copie : nouvelleInstance = instanceDeMonObjet
  • lorsque l’instance est retournée à la fin d’une fonction : return instanceDeMonObjet

Si un objet contient des pointeurs, il faut donc penser à créer un constructeur de copie (pour créer une vraie copie de ces pointeurs) afin d’éviter les destructions multiples, et donc les erreurs. Même si l’on prévoit d’utiliser cet objet via des pointeurs (donnée dynamique), il est préférable de créer tout de suite un constructeur de copie, afin d’éviter les erreurs futures.

Ah, et autre chose. D’après ce que l’on vient de dire sur la libération de données allouées dynamiquement, il apparaît que l’on n’a pas besoin de libérer un tableau alloué dynamiquement. Si on utilise directement int myArray[12] dans le déclaration d’une classe, ou dans une méthode : pas besoin de delete[]. Cool !

J’espère avoir l’occasion de revenir sur ce sujet afin de fixer quelques exemples sur le papier la toile 😉

Une réponse à Petit point sur C++ et la gestion mémoire

  1. Eh mais cet article est trop bien ! J’avais oublié qu’à une époque c’était aussi claire dans ma tête ><

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*