8
votes

Pourquoi utiliser 'errno' du tout?

Je suis un étudiant CS à la technion, je viens de tirer des appels de fonction variable et de style CSRNO . Cela me fait de moi, si SysCalls de style C utilise des registres pour renvoyer une valeur, pourquoi toute personne doit-elle utiliser errno du tout?


7 commentaires

N'était pas errno une chose de stdlib au lieu de faire quoi que ce soit avec SysCalls sous Linux?


@Joey je pensais la même chose.


Erno est une décision de conception de 30 à 35 ans (ou était-ce plus âgée?); Essayer de la comprendre maintenant, dans le contexte des machines d'aujourd'hui (de vastes plus puissantes) et des langues (beaucoup plus complexes et plus capables) ne va probablement pas aider beaucoup. C'est comme ça.


S'il vous plaît ne pas utiliser à moins que je donne la permission! (J'ai été regardé par de nombreux programmeurs C lors de la présentation de moi-même ...)


@Erno: Êtes-vous vraiment une décision de conception de 30 à 35 ans?


@Catcall, je suis un peu plus âgé que ça, mais le design va de l'arrière de Waaaay;)


@FredNurk FYI L'ERRNO est la principale source d'un message sur les erreurs sur GNU / Linux. Presque tout ce qui pourrait se produire - réseau, système de fichiers, autorisation - est renvoyé via Errno. Et IMAO Windows®'s CherroplerRor (GetLasterRor () »et« FormatMesage () »Versus Standard« Errno »et« Perror () / StreRror () »est une overcilleuse.


4 Réponses :


2
votes

Le meilleur exemple que je peux penser est la fonction STDIO FOPEN , qui renvoie NULL à l'échec et le seul moyen de savoir pourquoi il a échoué sur ERRNO et / ou PERROR.

Il doit y avoir d'autres exemples. C'est ce qui est juste à quoi ressotez-vous pour le moment.


2 commentaires

Merci pour la réponse rapide. Ce que je voulais dire, c'est pourquoi (par exemple) fopen utilise Erno depuis la première place?


Sinon, cela aurait pu avoir un autre paramètre pour stocker l'erreur possible. Quelque chose comme fopen (... int * err). Si vous demandez pourquoi ils ont choisi une méthode sur l'autre, je ne peux pas répondre à cela pour le moment.



4
votes

errno est une chose compliquée, en ce qu'il s'agit d'une interface historique qui, de nos jours, personne ne conçoit probablement comme ça. En outre, sur la plupart des systèmes, il ne ressemble à une variable qu'à une variable, ce n'est pas un. Habituellement, il est implémenté comme une macro qui cache un appel de fonction et que l'appel de la fonction renvoie une condition d'erreur spécifique de fil.


3 commentaires

Puis-je utiliser ceci pour mon bio? Je suis assez compliqué ... (désolé ne pouvait pas résister ;-))


@Erno, non, non, non. Premièrement, obtenez votre orthographe corrigée ou inventez une histoire pour laquelle vous deviez utiliser un nom de 5 lettres en raison de la restriction de stockage ou de la part de la restriction de stockage. Vous ne sortirez pas avec cela aussi facile que cela.


Mon logiciel d'orthographe retourne un errno quand j'échange Errno parce que j'ai ajouté ERNO au dictionnaire. Peut-être que Erno devrait causer un errno parce qu'il est mal orthographié ...



8
votes

La conception de la bibliothèque C a été effectuée il y a longtemps en même temps que début Unix. L'utilisation d'un code d'erreur distincte n'est pas un motif non rare (Win32 a le similaire GetLasterRor ()). Et il a des avantages superficiels.

Si vous décidez que vous souhaitez qu'une classe de fonctions ait une valeur de retour couramment utilisée, vous ne pouvez pas l'utiliser facilement pour renvoyer des erreurs. Par exemple, imaginez une API hypothétique P>

mytime_t t = get_current_time();
mysize_t s = get_window_size();


1 commentaires

Bien que "errno_t e; myTime_t t = get_current_time (& E);" fait une meilleure comparaison.



13
votes

La principale raison de l'utilisation errno est de donner plus d'informations sur la condition d'erreur.

Ceci est particulièrement utile dans des situations où la plupart (ou même tous les ) sont utiles. Les valeurs de retour d'une fonction sont en réalité valides valides valides.

Considérez la fonction fopen () , qui renvoie un pointeur sur un fichier < / code>. Chaque valeur de retour possible est également une valeur de retour valide, sauf null . Donc fopen () retourne null sur une défaillance. Mais alors vous ne pouvez pas dire ce que fait exactement la fonction échoue. Par conséquent, fopen () utilise errno pour désigner la condition d'erreur exacte, c'est-à-dire que le fichier n'existe pas, ou vous n'avez pas la permission de le lire ou du système. est hors de mémoire, ou autre chose.

Vous pouvez penser à errno en tant que variable globale (qu'elle était utilisée jusqu'à ce que les threads soient populaires). De nos jours, errno est généralement une macro emballage d'un appel de fonction renvoyant la condition d'erreur. Mais il s'agit simplement de la manière de la mise en œuvre de variables globales spécifiques à thread.

Les alternatives à errno sont moins confortables:

Vous pouvez fournir une fonction avec un pointeur sur un int et la fonction peut stocker sa condition d'erreur là-bas. strtod () est un bon exemple de cette technique. Mais cela rend l'API plus compliqué et donc moins souhaitable. En outre, il oblige le programmeur à définir un nouveau int , qui est gênant si vous ne vous souciez pas si la fonction échoue si la fonction échoue.

dans des langues qui permettent plus d'une valeur de retour ( et ne figurez pas d'exceptions), il est courant de renvoyer deux valeurs: une pour le résultat réel et une autre pour indiquer la condition d'erreur. Dans des langues comme aller, vous voyez le code comme ce qui suit: xxx

Ne faites pas confiance aux personnes qui prétendent que errno est une technique "ancienne" et Par conséquent, être évité. La machine que vous programmation est beaucoup plus ancienne que errno ou même c, et personne ne s'est jamais plaint de cela.


8 commentaires

Merci. C'était utile. Je ne sais toujours pas pourquoi seuls les appels SYS utilisaient cette fonction variable et toutes les fonctionnalités de l'espace utilisateur


En fait, beaucoup de fonctions de la bibliothèque standard C utilisent errno , par ex. MALLOC () ou FOPEN () . Connaissez-vous la différence entre les appels système, Standard Fonctions de bibliothèque et fonctions de la bibliothèque?


Je demande à votre affirmation que personne ne s'est jamais plaint de C :)


Cela pourrait être raisonnable pour une API de haut niveau, mais envisager Linux SysCall Warper API, le syscall actuel retournera toujours une INT à travers un registre, les valeurs négatives indiquent différents types d'erreurs et de valeurs non négatives indiquent le succès. L'utilisation de errno pour de telles interfaces fait une machine d'état anti-humanité dure à utiliser, la valeur de retour directe rendrait la plus proche de l'API du véritable noyau abi et plus facile à comprendre.


Les exceptions ne sont pas toujours meilleures que les numéros d'erreur, en particulier lorsque l'erreur est censée être traitée par son immédiat, c'est-à-dire que l'erreur est réellement vérifiée et traitée sur place.


Qu'en est-il des API Linux, par exemple int fd = ouvert (...); ? Une FD valide est positive, il y a donc beaucoup de place pour transmettre le code d'erreur via une valeur négative, mais errno est toujours utilisé ...


@ Tomeksowiński errno pour Ouvrir (2) est le résultat de l'emballage de l'appel du système spécifique à Linux réel par glibc pour fournir une interface POSIX de l'appel du système standard.


@Ruslan OK, donc c'est POSIX PAS LINUX. N'explique toujours pas Pourquoi Posix n'a pas utilisé la valeur de la poignée négative pour transmettre le code d'erreur.