12
votes

Comment fermer stdout et stardr en C?

J'ai besoin de fermer stdout et stardr pour l'un de mes programmes C. Comment est-il possible sans quitter le programme dans l'exécution?


4 commentaires

Pourquoi voulez-vous les fermer? Qu'espérez vous accomplir?


Que vous attendez-vous lorsque vous les fermez?


@Joseph il pourrait vouloir mettre le processus en arrière-plan. Dans ce cas, vous ferez toujours mieux de fermer tous les descripteurs de fichiers standard afin que vous ne finissez pas les avoir invalidés.


Je voulais juste diriger la sortie STDOUT et STDERR dans un fichier journal au lieu de la console. Désolé d'avoir répondu tard. Je l'ai travaillé maintenant.


5 Réponses :


8
votes

Qu'avez-vous essayé? Ne fclose fonctionne pas?


4 commentaires

@LHF Alors comment l'ouvrir à nouveau?


@tropy, il n'y a aucun moyen de l'ouvrir à nouveau.


Vous pouvez le rouvrir en utilisant Freopen ("/ dev / tty", "W", stdout); Ceci est souvent utilisé si un appel à exécuté échoue.


Fermer l'un des 3 flux par défaut dangereux, avec des ramifications potentiellement persistantes pour la machine réelle que vous avez exécutable?



50
votes

Vous pouvez simplement:

fclose(stdout);
fclose(stderr);


5 commentaires

... la raison de le faire est de dissocier le processus du TTY qui l'a débuté (s'il a été démarré à partir d'un TTY).


Les fermer sans ouvrir un remplacement (par exemple / dev / null ) est une très mauvaise idée et généralement dangereuse.


Vous avez la raison de la raison. L'écriture sur un fichier fermé (STDIO Stream) est UB, mais écrire dans un descripteur de fichier fermé est juste eBadf . En tout état de cause, la raison plus importante est qu'une autre partie du processus de programme ou d'enfant pourrait ouvrir ultérieurement un fichier important, qui sera attribué au premier numéro de descripteur de fichier non utilisé. Si FD 0, 1 ou 2 est inutilisé, le nouveau descripteur de fichier prendra la place de STDIN, STDOUT ou STDRERR, et pourrait être encombré par une autre partie du programme (ou processus enfant) qui utilise l'un de ces éléments pour leur habituel. Des fins ...


-1. C'est toujours un mauvais conseil et cela s'allume sur Google. NE PAS FCLOSE STDERR, c'est probablement un mauvais bogue. freopen () starr to / dev / null ou do DUP2 (Somenullfd, 2) .


@Nicholaswilson Oui, je sais. J'ai abordé cette question à l'époque, cependant, pour le rendre plus explicite, j'ai rééclamé la réponse à intégrer tous les commentaires ci-dessus.



2
votes

Si vous souhaitez empêcher votre application d'écrire à la console, alors: xxx

sorties: xxx

note : Toute tentative d'utilisation d'un pointeur de fichier après la fermeture du fichier est erronée. Je le fais dans ce cas simplement pour illustrer ce que fermer ces descripteurs de fichiers pourrait faire à votre application.


3 commentaires

Ce code a un comportement indéfini (à l'aide d'un fichier * une fois le fichier fermé). Cela pourrait tout aussi bien planter ou pire.


@R Cette partie du code que vous avez mentionné est juste pour illustrer ce que l'application fait depuis que le questionneur n'a pas répondu à nos commentaires sur ce qu'il devrait arriver après la fermeture de Stdout / Stdout. Puisque j'ai ajouté un avertissement dans la réponse à ce sujet, je ne suis pas sûr que je mérite toujours le -1, mais merci de toute façon.


J'ai enlevé le -1, mais "fera" est toujours erroné. En disant que c'est ce qu'il "pourrait faire" serait mieux, mais de toute façon, vous devez noter que le code exemple a comportement non défini et est un programme incorrect.



2
votes

Avertissement: Je ne suis pas expérimenté dans C du tout, mais a récemment lu une diapositive qui répond directement à cette question directement par Jim Meyering, un employé de Redhat et Gnulib Mainteneur: https://www.gnu.org/ghm/2011/paris/slides/jim-meyering-goodbye -world.pdf . Je suis simplement résumée.

tl; dr

Obtenez closeout.c et ses dépendances de gnulib dans votre source et appelle xxx

comme votre première ligne dans la principale.

Résumé

Premièrement, certains avertissements de tête, citant POSIX < / a>:

puisque après l'appel à FLOSE () Toute utilisation des flux entraîne un comportement non défini, FCLose () ne doit pas être utilisé sur STDIN, STDOUT ou STDERR, sauf immédiatement avant la résiliation du processus, ...... s'il y en a Atexit () Les gestionnaires enregistrés par l'application, un tel appel à FLOSE () ne doit pas se produire tant que le dernier gestionnaire est terminé. Une fois que FLOSE () a été utilisé pour fermer Stdin, STDOUT ou STDRERR, il n'y a pas de moyen standard de rouvrir l'un de ces flux.

Utilisation de Fermer () sur des descripteurs de fichier STDIN_FILENO, stdout_fileno ou stardr_fileno doit immédiatement être suivi d'une opération pour rouvrir ces descripteurs de fichiers. ...... En outre, une approche () suivie d'une opération de réouverture (par exemple ouvert (), dup (), etc.) n'est pas atomique; DUP2 () doit être utilisé pour modifier les descripteurs de fichiers standard.

Le flux de fermeture sans manipuler ses erreurs n'est pas robuste, et c'est la même chose pour stdout et stardr. Voici une liste d'erreurs dont vous avez besoin pour gérer:


0 commentaires

1
votes

En réalité, vous pouvez également utiliser la fonction fermeture : xxx


0 commentaires