173 votes

Définition de la variable sur NULL après free

Dans mon entreprise, il existe une règle de codage selon laquelle, après avoir libéré de la mémoire, réinitialisez la variable sur NULL. Par exemple ...

 void some_func () 
{
    int *nPtr;

    nPtr = malloc (100);

    free (nPtr);
    nPtr = NULL;

    return;
}
 

Je pense que, dans des cas comme le code présenté ci-dessus, la définition de NULL n'a aucune signification. Ou est-ce que je manque quelque chose?

S'il n'y a aucun sens dans de tels cas, je vais en parler à "l'équipe qualité" pour supprimer cette règle de codage. S'il vous plaît des conseils.

309voto

Martin v. Löwis Points 61768

Paramètre inutilisé pointeurs à NULL est un style défensif, la protection contre les balançant pointeur de bugs. Si un bancales pointeur est accessible après il est libéré, vous pouvez lire ou écraser à la mémoire vive. Si un pointeur null est accessible, vous obtenez immédiatement un crash sur la plupart des systèmes, vous dire tout de suite quelle est l'erreur.

Pour les variables locales, il peut être un peu inutile si il est "évident" que le pointeur n'est pas plus accessible après avoir été libéré, de sorte que ce style est plus approprié pour les données des membres et des variables globales. Même pour les variables locales, il peut être une bonne approche si la fonction se poursuit après la mémoire est libérée.

Pour compléter le style, vous devez également initialiser les pointeurs à NULL avant on leur attribue une véritable valeur du pointeur.

42voto

Mike McNertney Points 189

La plupart des réponses ont mis l'accent sur la prévention d'une double gratuit, mais le réglage du pointeur à NULL a un autre avantage. Une fois que vous libérer un pointeur, qui de mémoire est disponible pour être réaffectés par un autre appel à malloc. Si vous avez toujours l'original pointeur autour de vous pourriez vous retrouver avec un bug où vous essayez d'utiliser le pointeur après libre et corrompre une autre variable, et ensuite votre programme entre dans un état inconnu, et toutes sortes de mauvaises choses peuvent se produire (se bloquer si vous avez de la chance, la corruption de données si vous êtes malchanceux). Si vous deviez définir le pointeur à NULL après libre, toute tentative de lecture/écriture par le biais de ce pointeur plus tard, le résultat serait une erreur de segmentation, qui est généralement préférable au hasard à une corruption de la mémoire.

Pour ces deux raisons, il peut être une bonne idée de mettre le pointeur à NULL après free(). Il n'est pas toujours nécessaire, cependant. Par exemple, si le pointeur de variable est hors de portée immédiatement après free(), il n'y a pas beaucoup de raisons de le mettre à NULL.

40voto

AndreyT Points 139512

Paramètre un pointeur vers NULL après free est une pratique douteuse qui est souvent popularisé comme une "bonne programmation" règle manifestement fausse prémisse. C'est l'une de ces fausses vérités qui appartiennent à la "sonne juste" de la catégorie, mais en réalité atteindre absolument rien d'utile (et parfois conduit à des conséquences négatives).

Apparemment, paramètre un pointeur vers NULL après free est censé empêcher le terrible "double" problème lors de la même valeur du pointeur est passé de free plus d'une fois. En réalité, si, dans 9 cas sur 10, le véritable "double" problème se produit lorsque différents pointeur des objets ayant la même valeur de pointeur sont utilisés comme arguments pour free. Inutile de dire que, paramètre un pointeur vers NULL après free réalise absolument rien pour empêcher le problème dans ce cas.

Bien sûr, il est possible d'exécuter en "double" problème lors de l'utilisation de la même pointeur de l'objet comme argument d' free. Cependant, dans la réalité des situations comme ça normalement indiquer un problème avec le général de la structure logique du code, non pas un simple accidentelle "double". Une bonne façon de traiter le problème dans ce cas est de revoir et de repenser la structure du code, afin d'éviter la situation où le même pointeur est passé de free plus d'une fois. Dans de tels cas, le réglage du pointeur à l' NULL et en considérant que le problème est "résolu" n'est rien de plus qu'une tentative de balayer le problème sous le tapis. Il ne fonctionnera pas dans le cas général, parce que le problème avec la structure du code qui sera toujours à trouver une autre façon de se manifester.

Enfin, si votre code est spécifiquement conçu pour s'appuyer sur le pointeur de la valeur en NULL ou non, NULL, il est parfaitement bien pour définir la valeur du pointeur d' NULL après free. Mais en général les "bonnes pratiques" de la règle (comme dans "toujours configurer votre pointeur à l' NULL après free"), il est, une fois de plus, un fait bien connu et assez inutile, faux, souvent suivis par certains pour des raisons purement religieux, le vaudou comme raisons.

20voto

razzed Points 1751

Ceci est considéré comme une bonne pratique pour éviter d'écraser la mémoire. Dans la fonction ci-dessus, cela est inutile, mais souvent, lorsque cela est fait, il peut trouver des erreurs d'application.

Essayez quelque chose comme ceci à la place:

 #if DEBUG_VERSION
void myfree(void **ptr)
{
    free(*ptr);
    *ptr = null;
}
#else
#define myfree(p) do { void ** __p = (p); free(*(__p)); *(__p) = null; } while (0)
#endif
 

DEBUG_VERSION vous permet de profiler libère dans le code de débogage, mais les deux sont fonctionnellement identiques.

Edit : Added do ... alors que comme suggéré ci-dessous, merci.

7voto

Jared Oberhaus Points 8877

Paramètre le pointeur à l' free'd de la mémoire signifie que toute tentative d'accès à cette mémoire via le pointeur sera immédiatement crash, au lieu de provoquer un comportement indéfini. Il rend beaucoup plus facile de déterminer où les choses ont mal tourné.

Je peux voir votre argument: depuis nPtr est hors de portée de la droite après l' nPtr = NULL, il ne semble pas être une raison pour le mettre en NULL. Toutefois, dans le cas d'un struct membre ou à tout autre endroit où le pointeur n'est pas immédiatement d'aller hors de portée, il fait plus de sens. Il n'est pas immédiatement évident de savoir si ou non le pointeur sera à nouveau utilisée par le code qui ne devrait pas l'utiliser.

Il est probable que la règle est déclaré sans faire une distinction entre ces deux cas, car il est beaucoup plus difficile d'appliquer automatiquement la règle, encore moins pour les développeurs de le suivre. Il ne fait pas de mal à définir des pointeurs vers NULL après chaque gratuit, mais il a le potentiel de mettre en évidence de gros problèmes.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X