Quelle taille dois-je prévoir pour strerror_r?
La OpenGroup POSIX.1-2001 définit strerror_r, comme le fait Le Linux Standard Base Des Spécifications 3.1. Mais je ne peux trouver aucune référence à la taille maximale que pouvait raisonnablement attendre d'un message d'erreur. Je m'attendais à quelque définir quelque part que je pourrais mettre dans mon code, mais il n'en est aucun que je peux trouver.
Le code doit être thread-safe. C'est pourquoi strerror_r est utilisé et pas strerror.
Croit-on savoir le symbole que je peux utiliser? Je dois-je créer mon propre?
Exemple
int result = gethostname(p_buffy, size_buffy);
int errsv = errno;
if (result < 0)
{
char buf[256];
char const * str = strerror_r(errsv, buf, 256);
syslog(LOG_ERR,
"gethostname failed; errno=%d(%s), buf='%s'",
errsv,
str,
p_buffy);
return errsv;
}
De documents:
Le Groupe De Base Des Spécifications Question 6:
ERREURS
La strerror_r() la fonction peut échouer si:
- [ERANGE] de stockage Insuffisant a été fourni via strerrbuf et buflen à
contenir le message généré chaîne.
À partir de la source:
glibc-2.7/glibc-2.7/string/strerror.c:41:
char *
strerror (errnum)
int errnum;
{
...
buf = malloc (1024);
- Notez qu'au lieu d'utiliser
strerror
de la fonction, vous pouvez utilisersyslog
avec%m
spécificateur (qui est POSIX-compliant). Exemple:syslog(LOG_ERR, "Error occured, details: %m")
. Liresyslog
manuel pour en savoir plus. Malheureusement, je ne sais pas si%m
est thread-safe commestrerror_r
est.
Vous devez vous connecter pour publier un commentaire.
Avoir une assez grande statique limite est probablement assez bon pour toutes les situations.
Si vous avez vraiment besoin pour obtenir l'intégralité du message d'erreur, vous pouvez utiliser le Version GNU de strerror_r, ou vous pouvez utiliser la version standard
et sondage avec successivement plus grands tampons jusqu'à ce que vous obtenez ce que vous avez besoin. Par exemple,
vous pouvez utiliser quelque chose comme le code ci-dessous.
strerror_r
, à partir du lien que tu as donné: (la chaîne peut être tronquée si buflen est trop petit). Comment est-ce à résoudre le problème?+=
au lieu de*=
; fixation.strerror_r
interface de mettre encore moins de pensée dans ce que l'originalstrerror
. Ceci est illustré mauvaise conception, pas d'encapsulation à tous.Je ne serais pas s'inquiéter à ce sujet - d'une taille de mémoire tampon de 256 est beaucoup plus que suffisant, et 1024 est exagéré. Vous pouvez utiliser
strerror()
au lieu destrerror_r()
, et puis éventuellementstrdup()
le résultat si vous avez besoin de stocker la chaîne de l'erreur. Ce n'est pas thread-safe, cependant. Si vous avez vraiment besoin d'utiliserstrerror_r()
au lieu destrerror()
pour la sécurité des threads, il suffit d'utiliser une taille de 256. Dansglibc-2.7
, la plus longue chaîne de message d'erreur est de 50 caractères ("Invalide ou incomplète multi-octets ou de caractères larges"). Je ne serais pas s'attendre à l'avenir les messages d'erreur à être beaucoup plus de temps (dans le pire des cas, quelques octets de plus).U+0800
. Pour idéographique langues ce n'est pas un problème, parce que les personnages sont de 3 octets au lieu de 1 octet chacun, les mots sont souvent 1-2 caractères au lieu de 6 à 12 caractères. Mais dans d'autres non-Latin-langues à alphabet (en particulier S des scripts) j'ai pu voir des messages d'erreur facilement atteindre 256 octets.Ce programme (exécuter en ligne (comme C++) ici (d'ailleurs, quelqu'un sait comment faire pour compiler pur C en ligne?):
listes et imprime toutes les erreurs sur le système et de garder une trace de la longueur maximale. Par les regards de celui-ci, la longueur ne dépasse pas 49 caractères (pur
strlen
's sans\0
) donc avec une certaine marge de manœuvre, 64-100 devrait être plus que suffisant.Je suis curieux de savoir si l'ensemble de la taille de la mémoire tampon de négociation ne pouvait pas simplement être évitée par un retour aux structures et s'il y a une raison fondamentale pour ne pas revenir les structures. Donc je comparés:
et la différence de performance entre les deux au -O2 est minime:
En tout cas, je pense que c'est extrêmement bizarre que
strerror
est même permis de thread dangereux. Ces chaînes renvoyées doivent être des pointeurs vers des chaînes de caractères littérales. (Merci de m'éclairer, mais je ne peux pas penser à un cas où ils devraient être synthétisés à l'exécution). Et les littéraux de chaîne sont, par définition, en lecture seule et l'accès à la lecture seule des données est toujours thread-safe.strerror
peut pas être thread-safe dans les commentaires de cette réponse.