J'utilise une API et je me trouve écrire beaucoup de code de traitement des erreurs de la forme générale: où le corps de Cependant, il s'agit d'une douleur au code de la fonction à chaque fois. Y a-t-il un moyen d'obtenir le nom de la fonction provoquant l'erreur, c'est-à-dire impressionError code> pourrait ressemblent à: p>
4 Réponses :
La solution ici est de faire une macro qui invoque votre fonction, et s'il échoue, appelez une fonction d'impression avec vos paramètres spéciaux. Si vous utilisez C99, vous pouvez (AB) utiliser une macro variable, comme ceci: Notez que ce qui précède utilise un GCC Extension (qui est également pris en charge dans Clang) qui permet d'adopter des arguments variadiques d'être correctement passés si aucun n'était fourni. p> qui pourrait ensuite être utilisé comme tel: p> qui génère ce texte charmant pour votre plaisir de débogage: p>
Error in function fail on line 703 of file /Users/rross/Documents/TestProj/TestProj/main.mm: Couldn't validate results: Context-Sensitive Debug Info
Notez que c ++ 11 a des macros variadiques aussi :)
@chris en effet, mais en C ++, vous pourriez probablement faire quelque chose de bien meilleur avec les modèles.
Peut-être en dessous, mais pas pour passer le fichier et la ligne :(
@chris de quoi parlez-vous? Vous pouvez passer un const char * code> dans un modèle tout simplement bien.
Désolé, je voulais dire inclure __ ligne __ code> et __ fichier __ code> sans les spécifier explicite explicitement. Seule la substitution de texte des macros peut le faire. Vous pouvez en faire un seul pour le faire et remettre tout l'autre travail à un modèle, cependant.
+1, bien que l'erreur OUPUTS Succès code> pour le nom de la fonction lorsque vous aviez invoqué échec () code>.
Élégant, mais quel est le bénéfice de la liste des arguments variable sur quelque chose de plus simple comme la solution de XLC?
@ 1 "Si vous devez mettre plus d'informations de débogage, telles que lors de l'utilisation de Bind code>, vous pouvez émettre des numéros de socket, des descripteurs de fichier, etc. Avant de planter. Il est toujours bon d'avoir beaucoup d'endroits pour déboguer .
Il vous permet de créer un plus compliqué code> comme chaîne de format et arguments associés.
C'est assez cool, en fait! Je vais accepter XLC cependant, parce que c'est celui que j'ai réellement utilisé.
Vous pouvez avoir ce
Que fait le #func code> faire? Contrairement à #Line code>, ce n'est pas une directive pré-traitement autonome.
@ 1 "Il convertit une argument macro en une chaîne.
+1 avait la même pensée, mais il y a des inconvénients. Le plus grand est que le succès ou l'échec de la callee est caché de l'appelant. Si chaque erreur provoque le programme EXIT CODE>, c'est bon, mais si la manipulation est plus nuancée, cela devient un obstacle important.
@jerry Vous pouvez modifier cela pour le faire "renvoyer" le code d'erreur et le vérifier pour la fonction que vous souhaitez des soins supplémentaires. quelque chose comme #define sûre_call (FUNC) ({if (ERRORCODE = (FUNC)), impressionnez (...); ErrorCode;}) code>
Cela ne "retournera" rien, cela ne devrait pas compiler quel que soit la façon dont vous l'utilisez [bien que j'ai été surpris avant :)].
@jerry ({}) code> est une extension GCC gcc.gnu.org/onlinedocs/gcc/statement-expr.tml#statement-ex PRS
Eh bien, comme je l'ai dit, j'ai été surpris avant :) Encore, cela peut être fait de manière plus portable avec l'opérateur ternaire (aka conditionnel) ou un appel de la fonction (voir ma réponse par exemple, bien que c'est assez simple) .
nb: cette solution ne fonctionne que si l'API peut être modifiée ou enveloppée pour modifier le type de retour du code d'erreur. em> Je renforcerais le code de code code> Valeur avec le nom de la fonction qui renvoie le code. Ensuite, la fonction donc, la fonction quand Le retour d'une erreur utiliserait: Par exemple: p> impressive () code> peut extraire les informations du code code> code> lui-même. P> retour error_code (xyz); code>. Le récepteur du code d'erreur reçoit le nom de la fonction de la fonction qui a renvoyé l'erreur. La fonction la plus interne qui a déclenché l'erreur peut même être de retour correctement propagée si le code d'erreur est copié au lieu de réformé. P> void foo () {
error_code_type errorCode;
if ((errorCode = the_api_function()).code) {
printError(errorCode.code, errorCode.function, __LINE__, __FILE__);
}
}
Comme moi, j'ai malheureusement malheureusement malheureusement. Il cherche le nom de la fonction qu'il appelle, pas le nom de celui qu'il est actuellement.
@ RICHARDJ.ROSSIII: Non, j'ai attrapé ça. Lisez ma réponse avec soin.
Ce qui vous manque, c'est que __ func __ code> est inutile pour ce qu'il tente de faire ici.
@ Richardj.rossiii: le __ func __ code> est utilisé par la fonction appelée qui a provoqué l'erreur. Il est retourné à l'appelant, l'appelant sait donc quelle fonction a provoqué l'erreur.
Mais je ne peux pas modifier la fonction qui a provoqué l'erreur, car cela fait partie de l'API.
@ 1 '': J'envelopperais moi-même les API afin que je puisse avoir un contrôle complet sur la manière dont l'API est utilisée. Si ce n'est pas une option, je recommanderais la solution de XLC ou de Richardj.rossiii.
Si vous n'avez pas Errorcode code> défini (ou ne voulez pas toujours le définir), utilisez ceci à la place: P> error: call func(1,1,1) shouldn't have returned 1 but did (from function main at line 38 of file prog.c)
error: call func(a,b,c) returned 0 instead of 1 (from function main at line 40 of file prog.c)
error: call func(a,b,1) returned 1 (from function main at line 42 of file prog.c)
error: call func2() returned -1 (from function main at line 44 of file prog.c)
func2 failed error check
error: call funcPoint() returned -1 (from function main at line 53 of file prog.c)
funcPoint failed error check
func passed error check
error: call func3() returned 3 (from function main at line 71 of file prog.c)
retry...
error: call func3() returned 2 (from function main at line 71 of file prog.c)
retry...
error: call func3() returned 1 (from function main at line 71 of file prog.c)
retry...
error: call func(1,2,4) returned 7 (from function main at line 76 of file prog.c)
fatal error 7
J'ai manqué l'opérateur des virgules là-bas, apparemment.
#define error_location __func__, __line__, __fle __ code> etprintError (ErrorCode, error_location); code> est le long des lignes de ce que je fais habituellement ou mettez l'appel entier dans une macro. Le premier est un peu plus flexible pour avoir une macro pour toutes les surcharges deprintError code>.@chris je ferais attention avec ça. La meilleure option est de créer une macro paramètre que vous invoquez comme une fonction. Passer trois arguments qui ressemblent à un mène à certaines ... situations intéressantes.
@ RICHARDJ.ROSSIII, Tant qu'il est clair qu'il ne devrait être utilisé que pour appeler des fonctions d'erreur nécessitant la source de l'erreur, je ne vois aucun problème avec celui-ci étant utilisé pour cela. Y a-t-il quelque chose de spécifique que vous aviez à l'esprit?
@chris
__ func __ code> donne la fonction i "m actuellement dans, mais je veux le nom de la fonction API que je viens de rester.@ 1 '', je vois, j'inclus habituellement cela avec un message personnalisé si je le mettais. Il n'est pas difficile d'adapter quelle que soit la macro que vous utilisez, mais je n'ai pas trouvé de meilleur moyen que les macros à cette fin. C'est l'un des rares fois que j'utiliserai un.