La lecture des pages de manuel et du code ne m'a pas vraiment aidé à comprendre la différence entre - ou mieux, quand je devrais utiliser - perror("...")
ou fprintf(stderr, "...")
.
La lecture des pages de manuel et du code ne m'a pas vraiment aidé à comprendre la différence entre - ou mieux, quand je devrais utiliser - perror("...")
ou fprintf(stderr, "...")
.
Réponses:
L'appel perror
vous donnera la valeur interprétée de errno
, qui est une valeur d'erreur locale au thread écrite par les appels système POSIX (c'est-à-dire que chaque thread a sa propre valeur pour errno
). Par exemple, si vous avez fait un appel à open()
, et qu'une erreur s'est produite (c'est-à-dire qu'elle est retournée -1
), vous pouvez alors appeler perror
immédiatement après pour voir quelle était l'erreur réelle. Gardez à l'esprit que si vous appelez d'autres appels système entre-temps, la valeur de errno
sera écrasée et l'appel perror
ne sera d'aucune utilité pour diagnostiquer votre problème si une erreur a été générée par un appel système antérieur.
fprintf(stderr, ...)
d'autre part, peut être utilisé pour imprimer vos propres messages d'erreur personnalisés. En imprimant vers stderr
, vous évitez que votre sortie de rapport d’erreurs soit mélangée avec la sortie «normale» qui devrait aller vers stdout
.
Gardez à l'esprit que cela fprintf(stderr, "%s\n", strerror(errno))
est similaire à perror(NULL)
car un appel à strerror(errno)
générera la valeur de chaîne imprimée pour errno
, et vous pouvez ensuite combiner cela avec tout autre message d'erreur personnalisé via fprintf
.
strerror
n'est pas nécessaire pour être thread-safe. C'est stupide, mais c'est la norme. strerror_l
peut être utilisé à la place en remplacement instantané sur les systèmes POSIX 2008. strerror_r
est également disponible sur les systèmes plus anciens, mais présente des problèmes vraiment désagréables avec certains systèmes ayant des versions non conformes.
perror
ajoute '\n'
à la fin donc le format serait "%s\n"
, non?
strerror_s
n'est en fait pas trop mal comme interface.
_s
entrer leurs déchets dans la norme était essentiellement un jeu de MS ("Si vous adoptez nos interfaces, nous envisagerons de faire en sorte que nos produits prennent en charge votre norme.") Et bien sûr, maintenant, ils ne respectent pas. En fait, je suis d'accord que cette interface n'est pas mauvaise en soi. Ce qui est mauvais, c'est la propagande (sous forme d'avertissements du compilateur) selon laquelle la plupart de la bibliothèque standard est "non sécurisée" et que toute la famille de _s
fonctions devrait être utilisée à la place des fonctions standard.
Ils font des choses assez différentes.
Vous utilisez perror()
pour imprimer un message stderr
correspondant à errno
. Vous utilisez fprintf()
pour imprimer quoi que ce soit sur stderr
, ou tout autre flux. perror()
est une fonction d'impression très spécialisée:
perror(str);
est équivalent à
if (str)
fprintf(stderr, "%s: %s\n", str, strerror(errno));
else
fprintf(stderr, "%s\n", strerror(errno));
perror(const char *s)
: imprime la chaîne que vous lui donnez suivie d'une chaîne qui décrit la valeur actuelle de errno
.
stderr
: c'est un flux de sortie utilisé pour diriger vos propres messages d'erreur vers (par défaut vers le terminal).
Pertinent:
char *strerror(int errnum)
: donnez-lui un numéro d'erreur et il renverra la chaîne d'erreur associée.
perror () écrit toujours dans stderr; strerr (), utilisé avec fprintf (), peut écrire sur n'importe quelle sortie - y compris stderr mais pas exclusivement.
fprintf(stdout, "Error: %s", strerror(errno));
fprintf(stderr, "Error: %s", strerror(errno)); // which is equivalent to perror("Error")
De plus, perror impose son propre formatage de texte "texte: description d'erreur"
La fonction Perror prend plus de temps pour exécuter l'appel d'exécution passe de l'espace utilisateur à l'espace noyau, alors que les appels fprintf vont de l'api à kernal
If you use a function that effects errno then it makes sense to use perror
Si vous utilisez une fonction qui n'effectue pas errno et renvoie simplement un code d'erreur, vous devez utiliser fprintf (stderr, fmt, ...). Par exemple, strtol retournera LONG_MAX ou LONG_MIN si une chaîne est hors de portée et définira errno sur ERANGE. Donc, si strtol échoue en raison d'un hors de portée, j'utiliserais perror.