En supposant que votre compilateur C++ les prenne en charge, existe-t-il une raison particulière pas d'utiliser __FILE__
, __LINE__
et __FUNCTION__
pour des fins de journalisation et de mise au point?
Je m'occupe principalement de donner à l'utilisateur des données trompeuses - par exemple, signaler le numéro de ligne ou la fonction incorrects à la suite d'une optimisation - ou subir un impact négatif sur les performances.
Fondamentalement, puis-je faire confiance à __FILE__
, __LINE__
et __FUNCTION__
à toujours faire la bonne chose?
__FUNCTION__
n'est pas standard, __func__
existe dans C99/C++ 11. Les autres (__LINE__
et __FILE__
) conviennent parfaitement.
Il indiquera toujours le bon fichier et la bonne ligne (et fonctionnera si vous choisissez d'utiliser __FUNCTION__
/__func__
). L’optimisation n’est pas un facteur car il s’agit d’une expansion de macro à la compilation; cela va jamais affecter les performances de quelque manière que ce soit.
Dans de rares cas, il peut être utile de changer la ligne donnée par __LINE__
par quelque chose d'autre. J'ai vu GNU configure faire pour que certains tests signalent les numéros de ligne appropriés après avoir inséré du voodoo entre des lignes n'apparaissant pas dans les fichiers source d'origine. Par exemple:
#line 100
Les lignes suivantes commenceront par __LINE__
100. Vous pouvez éventuellement ajouter un nouveau nom de fichier.
#line 100 "file.c"
Ce n'est que rarement utile. Mais si cela est nécessaire, il n'y a pas d'alternative à ma connaissance. En fait, au lieu de la ligne, une macro peut également être utilisée, ce qui doit donner l’une des formes susmentionnées. En utilisant la bibliothèque de préprocesseur boost, vous pouvez incrémenter la ligne actuelle de 50:
#line BOOST_PP_ADD(__LINE__, 50)
J'ai pensé qu'il était utile de le mentionner puisque vous avez posé des questions sur l'utilisation de __LINE__
et __FILE__
. On n'a jamais assez de surprises en C++ :)
Edit: @Jonathan Leffler fournit quelques bons cas d'utilisation supplémentaires dans les commentaires:
Messing avec #line est très utile pour les pré-processeurs qui souhaitent conserver les erreurs signalées dans le code C de l'utilisateur en conformité avec le fichier source de l'utilisateur. Yacc, Lex et (plus à l'aise chez moi) les pré-processeurs ESQL/C font cela.
FYI: g ++ propose la macro non standard __PRETTY_FUNCTION__. Jusqu'à présent, je ne connaissais pas C99 __func__ (merci Evan!). Je pense que je préfère quand même __PRETTY_FUNCTION__ quand il est disponible pour la portée de 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. */
}
Personnellement, je suis réticent à les utiliser pour autre chose que les messages de débogage. Je l'ai fait, mais j'essaie de ne pas montrer ce type d'informations à des clients ou à des utilisateurs finaux. Mes clients ne sont pas des ingénieurs et ne maîtrisent parfois pas l’informatique. Je peux 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.
Je les utilise tout le temps. La seule chose qui m'inquiète, c'est de donner de l'IP dans les fichiers de log. Si les noms de vos fonctions sont vraiment bons, vous pourriez rendre un secret commercial plus facile à découvrir. C'est un peu comme l'envoi de symboles de débogage, mais il est plus difficile de trouver des choses. Dans 99,999% des cas, rien ne va en résulter.