J'ai donc creusé la façon dont la partie stdio de libc est implémentée et j'ai rencontré une autre question. En regardant man setvbuf
je vois le suivant:qui setvbuf tampon libre?
Lorsque la première opération I/O se produit sur un fichier, malloc (3) est appelé, et un tampon est obtenu.
Cela est logique, votre programme ne devrait pas avoir un malloc
dedans pour E/S à moins que vous utilisez réellement. Ma réaction viscérale à ceci est que la libc nettoiera son propre désordre ici. Ce que je ne peux que supposer, c'est parce que valgrind ne signale aucune fuite de mémoire (ils pourraient bien sûr faire quelque chose de sale et ne pas l'allouer via malloc
directement ... mais nous supposerons qu'il utilise littéralement malloc
pour l'instant).
Mais, vous pouvez spécifier votre propre tampon trop ...
int main() {
char *p = malloc(100);
setvbuf(stdio, p, _IOFBF, 100);
puts("hello world");
}
Oh non, fuite de mémoire! valgrind le confirme. Il semble donc que chaque fois que stdio alloue une mémoire tampon, elle sera automatiquement supprimée (au plus tard lors de la sortie du programme, mais peut-être aussi lors de la fermeture du flux). Mais si vous spécifiez explicitement le tampon, vous devez le nettoyer vous-même.
Il y a cependant un problème. La page de manuel dit aussi ceci:
Vous devez vous assurer que l'espace qui points de buf existe encore au moment flux est fermé, ce qui arrive aussi à la fin du programme. Par exemple, suivant est incorrect:
Maintenant cela devient intéressant pour les flux standards. Comment pourrait-on nettoyer correctement un tampon alloué manuellement pour eux, puisqu'ils sont fermés dans la terminaison du programme? Je ne pouvais imaginer un « nettoyer ce quand je ferme le drapeau » dans le struct fichier, mais il se poilue parce que si je lis ce droit de faire quelque chose comme ceci:
setvbuf(stdout, 0, _IOFBF, 0);
printf("hello ");
setvbuf(stdout, 0, _IOLBF, 0);
printf("world\n");
causerait 2 allocations par la bibliothèque standard en raison de cette phrase:
Si l'argument buf est NULL, seul le mode est affecté; un nouveau tampon sera alloué lors de la prochaine opération de lecture ou d'écriture .
EDIT: un addenda à ma question. Comme il est clair que je dois free
tampons que je passe à setvbuf
, si je l'utilise en fait sur stdout
est-il un moyen pratique de free
il? Il doit vivre à la fin du programme. Le mieux que je puisse penser est fclose(stdout)
puis le libérer ou utiliser un tampon statique comme certaines personnes l'ont mentionné. Je demande parce que cela semble être une décision de conception maladroite.
Mise à jour de la réponse vers un lien vers la page. C'est OS X, mais la page de manuel vient de FreeBSD (http://www.freebsd.org/cgi/man.cgi?query=setvbuf). – outis
Difficile de voir comment les choses pourraient être autrement, car on pourrait fournir un tampon statique qui ne doit pas être libéré avec free(). –
@Neil: en effet, je me demandais plus si le stdlib avait une fuite de mémoire à cause de la conception car il n'y a aucun moyen d'obtenir le tampon qu'il a affecté hors du flux. –