2009-02-27 6 views
114

que votre présumant compilateur C++ les prend en charge, est-il une raison particulière pas à utiliser __FILE__, __LINE__ et __FUNCTION__ à des fins d'exploitation forestière et de débogage? Je veux surtout donner à l'utilisateur des données trompeuses - par exemple, signaler un numéro de ligne ou une fonction incorrects suite à une optimisation - ou prendre un coup sur les performances.__FILE__, __LINE__, et l'utilisation de __FUNCTION__ en C++

Fondamentalement, je peux faire confiance __FILE__, __LINE__ et __FUNCTION__-toujours faire la bonne chose?

+0

__LINE__ devrait faire la bonne chose. Je l'ai beaucoup utilisé et ses cohortes, y compris __PRETTY_FUNCTION__. ... Mais ... eh bien, je suis juste en train de regarder le code où __LINE__ ment. Probablement parce qu'il se trouve dans un bloc catch pour la gestion des exceptions try/catch. –

+2

pertinent: [référence gcc pour les macros prédéfinies] (http://gcc.gnu.org/onlinedocs/cpp/Standard-Predefined-Macros.html) –

Répondre

140

__FUNCTION__ est non standard, __func__ existe en C99/C++ 11. Les autres (__LINE__ et __FILE__) vont bien.

Il indiquera toujours le bon fichier et la bonne ligne (et fonctionnera si vous choisissez d'utiliser __FUNCTION__/__func__). L'optimisation est un non-facteur puisqu'il s'agit d'une macro-expansion de compilation; il n'effectuera jamais les performances d'effet de quelque manière que ce soit.

+2

'__func__' est un peu un problème en C++. C99 ne dit pas un mot sur les arguments par défaut et ainsi de suite, les cas où ce n'est pas si évident comment '__func__' devrait se comporter en C++. – wilhelmtell

+3

@thr: alors que vous faites un bon point. J'étais assez clair que '__func__' existe en c99, pas en C++. Quoi qu'il en soit, je pense qu'une implémentation raisonnable de '__func__' en C++ aboutirait simplement au nom mutilé. Puisque je ne suis pas un rédacteur de compilateur, ce n'est pas vraiment mon appel. –

+0

Quels compilateurs ne prennent pas en charge '__FUNCTION__' du tout? Quels compilateurs sauf gcc récents traitent cela comme une variable, pas une macro? – basin

7

Personnellement, je suis réticent à les utiliser pour autre chose que le débogage des messages. Je l'ai fait, mais j'essaie de ne pas montrer ce genre d'informations aux clients ou aux utilisateurs finaux. Mes clients ne sont pas des ingénieurs et ne maîtrisent parfois pas l'informatique. Je pourrais enregistrer ces informations sur la console, mais, comme je l'ai dit, à contrecoeur, sauf pour les versions de débogage ou pour les outils internes. Je suppose que cela dépend de la clientèle que vous avez, cependant.

+21

"Je pourrais enregistrer ces informations sur la console" - ou mieux encore: enregistrez-le dans un fichier afin que si quelque chose ne va pas, vous pouvez demander au client de vous l'envoyer ... – Christoph

30

Dans de rares cas, il peut être utile de changer la ligne donnée par __LINE__ à autre chose. J'ai vu GNU configure faire cela pour certains tests afin de rapporter les numéros de ligne appropriés après avoir inséré du vaudou entre les lignes qui n'apparaissent pas dans les fichiers sources d'origine. Par exemple:

#line 100 

Apportera les lignes suivantes commencent par __LINE__ 100. Vous pouvez aussi ajouter un nouveau nom de fichier

#line 100 "file.c" 

Il est rarement utile. Mais si cela est nécessaire, il n'y a pas d'alternatives que je connaisse. En fait, au lieu de la ligne, une macro peut également être utilisée, ce qui doit aboutir à l'une des deux formes ci-dessus. Utilisation de la bibliothèque de préprocesseur boost, vous pouvez augmenter la ligne actuelle de 50:

#line BOOST_PP_ADD(__LINE__, 50) 

je pensais qu'il est utile de le mentionner, puisque vous avez demandé sur l'utilisation de __LINE__ et __FILE__. On n'a jamais assez de surprises obtient sur :) C++

Edit: Leffler fournit quelques @ Jonathan plus bon cas d'utilisation dans les commentaires:

Messing aveC#line est très utile pour les pré-processeurs souhaitez conserver les erreurs signalées dans le code C de l'utilisateur en ligne avec le fichier source de l'utilisateur. Yacc, Lex, et (plus à la maison pour moi) les préprocesseurs ESQL/C font cela.

22

FYI: g ++ offre la macro __PRETTY_FUNCTION__ non standard. Jusqu'à présent, je ne savais pas sur C99 __func__ (merci Evan!).Je pense que je préfère encore __PRETTY_FUNCTION__ quand il est disponible pour la portée de la classe supplémentaire.

PS:

static string getScopedClassMethod(string thePrettyFunction) 
{ 
    size_t index = thePrettyFunction . find("("); 
    if (index == string::npos) 
    return thePrettyFunction; /* Degenerate case */ 

    thePrettyFunction . erase(index); 

    index = thePrettyFunction . rfind(" "); 
    if (index == string::npos) 
    return thePrettyFunction; /* Degenerate case */ 

    thePrettyFunction . erase(0, index + 1); 

    return thePrettyFunction; /* The scoped class name. */ 
} 
+0

Bon à savoir sur le \ _ \ _ PRETTY_FUNCTION \ _ \ _. Très utile! – Maverobot

4

Je les utilise tout le temps. La seule chose qui m'inquiète est de donner l'adresse IP dans les fichiers journaux. Si vos noms de fonctions sont vraiment bons, vous pourriez faire un secret commercial plus facile à découvrir. C'est un peu comme une expédition avec des symboles de débogage, seulement plus difficile de trouver des choses. Dans 99,999% des cas, rien de mauvais n'en sortira.

+0

Bon point à aborder. Il est trivial d'extraire cette information en utilisant l'utilitaire 'strings' pour extraire toutes les données de type chaîne de l'exécutable. Même les exécutables compressés peuvent être extraits. Soyez très attentif à ce que vous envoyez sur un site client. Souvent, les concurrents peuvent mettre la main sur vos exécutables, même s'ils ne sont pas censés le faire. – Marty

Questions connexes