« Programmation C/Gestion de la mémoire » : différence entre les versions

Contenu supprimé Contenu ajouté
mAucun résumé des modifications
m typographie française
Ligne 1 :
<noinclude>{{Programmation C}}</noinclude>
La gestion dynamique de la mémoire en C se fait à l'aide de principalement deux fonctions de la bibliothèque standard :
* <code>malloc</code>, pour l'allocation dynamique de mémoire ;
* <code>free</code>, pour la libération de mémoire préalablement allouée avec <code>malloc</code>.
 
Deux autres fonctions permettent de gérer plus finement la mémoire :
* <code>calloc</code>, pour allouer dynamiquement de la mémoire, comme <code>malloc</code>, qui a préalablement été initialisée à 0 ;
* <code>realloc</code>, pour modifier la taille d'une zone mémoire déjà allouée.
 
Ligne 39 :
#La zone mémoire allouée, si l'appel réussit, n'est pas initialisée. C'est une erreur de conception grave que d'accéder au bloc mémoire en s'attendant à trouver une certaine valeur (0 par exemple).
 
Par exemple, si on souhaite réserver une zone mémoire pour y allouer un entier :
 
<source lang="c">
Ligne 215 :
 
==== Gestion d'erreur ====
Pour gérer correctement le cas d'échec, on ne peut faire ainsi :
 
{{Erreur volontaire}}
Ligne 230 :
</source>
 
En effet, si <tt>realloc</tt> échoue, la valeur de <tt>ptr</tt> est alors nulle, et on aura perdu la référence vers l'espace de taille <tt>10 * sizeof(int)</tt> qu'on a déjà alloué. Ce type d'erreur s'appelle une ''fuite mémoire''. Il faut donc faire ainsi :
 
<source lang="c">
Ligne 312 :
== Problèmes et erreurs classiques ==
=== Défaut d'initialisation d'un pointeur ===
Pour éviter des erreurs, un pointeur devrait '''toujours''' être initialisé lors de sa déclaration ; soit à NULL, soit avec l'adresse d'un objet, soit avec la valeur de retour d'une fonction « sûre » comme <tt>malloc</tt>. Méditons sur l'exemple suivant :
 
{{Erreur volontaire}}
Ligne 324 :
</source>
 
Ce code va compiler! Si on est chanceux l'exécution de ce code provoquera une erreur à la troisième étape lorsqu'on déréférence <code>ptr</code>. Si on l'est moins, ce code s'exécute sans souci et stocke dans <code>var</code> une valeur aléatoire, ce qui pourrait provoquer une erreur lors d'une utilisation ultérieure de la variable <code>var</code> alors que l'erreur réelle se situe bien plus en amont dans le code! Une variable (automatique) de type pointeur est en effet comme toutes les autres variables : si elle n'est pas initialisée explicitement, son contenu est indéfini ; son déréférencement peut donc causer n'importe quel comportement.
 
Lorsqu'on déclare une variable ou qu'on alloue une zone mémoire, on ne dispose d''''aucune''' garantie sur le contenu de cette zone ou de cette variable. Initialiser systématiquement les variables dès leur déclaration, en particulier lorsqu'il s'agit de pointeurs, fait partie des bons réflexes à prendre et pour la plupart des applications ne dégrade pas le temps d'exécution de manière significative. Ce type d'erreur peut être extrèmement difficile à localiser à l'intérieur d'un programme plus complexe.
Ligne 352 :
=== Fuite mémoire ===
 
La perte du pointeur associé à un secteur mémoire rend impossible la libération du secteur à l'aide de free. On qualifie cette situation de ''fuite mémoire'', car des secteurs demeurent réservés sans avoir été désalloués. Cette situation perdure jusqu'à la fin du programme principal. Voyons l'exemple suivant :
 
{{Erreur volontaire}}