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

Contenu supprimé Contenu ajouté
→‎<code>calloc</code> : ne pas caster la valeur de retour de *alloc
→‎<code>realloc</code> : débordement entier
Ligne 139 :
Lorsque <tt>realloc</tt> reçoit la valeur de <tt>tab</tt>, qui est un pointeur sur le premier élément (i.e. <tt>&tab[0]</tt>), il ne peut la traiter, et le comportement est indéfini. Sur cet exemple, il est facile de voir l'erreur, mais dans l'exemple suivant, la situation est plus délicate :
<pre>
#include <stdint.h> /* pour SIZE_MAX */
#include <stdlib.h>
 
/* 'double' essaye de doubler l'espace mémoire pointé par ptr.
Ligne 162 :
On peut aussi noter que, quand <tt>realloc</tt> réussit, le pointeur renvoyé peut très bien être égal au pointeur initial, ou lui être différent.
En particulier, il n'y a aucune garantie que, quand on diminue la taille de la zone mémoire, il le fasse « sur place ». C'est très probable, car c'est ce qui est le plus facile et rapide à faire du point de vue de l'implémentation, mais rien ne l'empêche par exemple de chercher un autre espace mémoire disponible qui aurait exactement la taille voulue, au lieu de garder la zone mémoire initiale.
 
On peut noter le test <tt>(n <= SIZE_MAX / 2)</tt>. Il permet d'éviter un ''débordement entier'' : si n était supérieur à cette valeur, le produit <tt>n * 2</tt> devrait avoir une valeur supérieure à <tt>SIZE_MAX</tt>, qui est la plus grande valeur représentable par le type <tt>size_t</tt>. Lorsque cette valeur est passée à <tt>realloc</tt>, la conversion en <tt>size_t</tt>, qui est un type entier non signé, se fera modulo <tt>SIZE_MAX + 1</tt>, et donc la fonction recevra une valeur différente de celle voulue. Si le test n'était pas fait, <tt>double</tt> pourrait ainsi retourner à l'appelant une zone mémoire de taille inférieure à celle demandée, ce qui causerait des bogues. Ce genre de bogue (non spécifique à <tt>realloc</tt>) est très difficile à détecter, car n'apparaît que lorsque l'on atteint des valeurs limites, ce qui est assez rare, et le problème peut n'être visible que bien longtemps après que l'erreur de calcul soit faite.
 
==== Gestion d'erreur ====