web-dev-qa-db-fra.com

Que signifie «double gratuit»?

Comme le titre l'indique, je suis nouveau à C et j'aurai bientôt un moyen terme. Je révise actuellement des articles antérieurs et un thème récurrent est le double problème gratuit. Je comprends que c'est le processus d'appeler free() sur le même emplacement mémoire deux fois, mais j'ai quelques questions auxquelles je ne suis pas sûr à 100% de savoir comment répondre:

Question 1: Quel est le résultat d'un double libre en C, et pourquoi est-ce un tel problème?

Cela entraînera un double gratuit:

char* ptr = malloc(sizeof(char));

*ptr = 'a';
free(ptr);
free(ptr);

Ma réponse à cela serait, est-ce qu'elle retournerait une adresse mémoire 0x0 et provoquerait une instabilité/plantage du système. De plus, si je me souviens bien, un double free peut en fait appeler malloc deux fois, ce qui entraîne un débordement de tampon, laissant ainsi le système vulnérable.

Quelle serait la meilleure façon de résumer brièvement cette question?

Question 2: Décrivez une situation dans laquelle il est particulièrement facile d'introduire un double gratuit en C?

Je pensais qu'en passant des pointeurs autour de vous, vous pourriez le libérer accidentellement dans une fonction, et le libérer à nouveau sans vous en rendre compte?

Encore une fois, quelle est la "meilleure" façon de résumer cela?

25
chris edwards

Un double libre en C, techniquement parlant, conduit à comportement indéfini. Cela signifie que le programme peut se comporter de manière complètement arbitraire et que tous les paris sont désactivés sur ce qui se passe. C'est certainement une mauvaise chose que cela se soit produit! Dans la pratique, la double libération d'un bloc de mémoire endommagera l'état du gestionnaire de mémoire, ce qui pourrait endommager les blocs de mémoire existants ou faire en sorte que les allocations futures échouent de manière bizarre (par exemple, la même mémoire étant distribuée sur deux différents appels successifs de malloc).

Les doubles libérations peuvent survenir dans toutes sortes de cas. Un assez courant est lorsque plusieurs objets différents ont tous des pointeurs les uns vers les autres et commencent à être nettoyés par des appels à free. Lorsque cela se produit, si vous ne faites pas attention, vous pouvez free le même pointeur plusieurs fois lors du nettoyage des objets. Il existe également de nombreux autres cas.

J'espère que cela t'aides!

26
templatetypedef

Parce que free () consolidera les régions adjacentes en gérant les informations stockées dans les balises avant chaque région. C'est quelque chose comme gérer la double liste chaînée. Il serait donc dangereux que le tampon vers lequel pointe ptr soit écrasé par une chaîne d'attaque, dans laquelle de fausses balises peuvent être injectées.

5
zero_yu

Cette question a été bien répondu, mais j'ajoute une réponse tardive en raison d'un lien "question en double", qui a demandé "comment l'éviter?"

Une ligne est ajoutée à l'exemple de code publié.

char* ptr = malloc(sizeof(char));

*ptr = 'a';
free(ptr);
ptr = NULL;         // add this
free(ptr);

La fonction free ne fait rien avec un pointeur NULL.

2
Weather Vane

Conformément à la norme C11 publiée, l'appel de free sur un emplacement de mémoire déjà free conduit à un comportement non défini. Cela peut conduire à des situations bizarres telles que la mémoire non allouée même lorsqu'elle est disponible, le tas corrompu, le même emplacement de mémoire alloué à différents mallocs, etc. Fondamentalement, il n'est pas défini et peut être n'importe quoi.

ANSI C11 std peut être trouvé ici. https://www.iso.org/obp/ui/#iso:std:iso-iec:9899:ed-3:v1:en

EDIT: changé NULL en déjà freed, basé sur les commentaires. aussi, le lien pointe maintenant vers ISO/IEC 9899: 2011 (fr)

0
ankurgupta7