__FILE__,__LINE__, y__FUNCTION__ uso en C++
debugging logging (5)
Presumiendo que su compilador C ++ los admite, ¿hay alguna razón particular para no usar __FILE__
, __LINE__
y __FUNCTION__
para __FUNCTION__
de registro y depuración?
Lo que más me preocupa es proporcionar al usuario datos confusos (por ejemplo, informar el número de línea incorrecto o la función como resultado de la optimización) o dar como resultado un golpe de rendimiento.
Básicamente, ¿puedo confiar en que __FILE__
, __LINE__
y __FUNCTION__
siempre hagan lo correcto?
En casos raros, puede ser útil cambiar la línea dada por __LINE__
a otra cosa. He visto que GNU configure hace eso para que algunas pruebas informen los números de línea apropiados después de insertar algún vudú entre líneas que no aparecen en los archivos fuente originales. Por ejemplo:
#line 100
Hará que las siguientes líneas comiencen con __LINE__
100. Opcionalmente puede agregar un nuevo nombre de archivo
#line 100 "file.c"
Rara vez es útil. Pero si es necesario, no hay alternativas que yo sepa. En realidad, en lugar de la línea, también se puede usar una macro que debe dar como resultado cualquiera de las dos formas anteriores. Con la biblioteca del preprocesador de impulso, puede incrementar la línea actual en 50:
#line BOOST_PP_ADD(__LINE__, 50)
Pensé que __FILE__
útil mencionarlo, ya que preguntaste sobre el uso de __LINE__
y __FILE__
. Uno nunca obtiene suficientes sorpresas de C ++ :)
Editar: @Jonathan Leffler proporciona algunos casos de uso más buenos en los comentarios:
Jugar con #line es muy útil para los preprocesadores que desean mantener los errores informados en el código C del usuario en línea con el archivo fuente del usuario. Yacc, Lex y (más en mi casa) los preprocesadores ESQL / C hacen eso.
FYI: g ++ ofrece la macro __PRETTY_FUNCTION__ no estándar. Hasta ahora no sabía sobre C99 __func__ (¡gracias Evan!). Creo que todavía prefiero __PRETTY_FUNCTION__ cuando está disponible para el alcance de clase adicional.
PD:
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. */
}
Los utilizo todo el tiempo. Lo único que me preocupa es regalar IP en los archivos de registro. Si los nombres de sus funciones son realmente buenos, podría estar haciendo que un secreto comercial sea más fácil de descubrir. Es como enviar con símbolos de depuración, solo que es más difícil encontrar cosas. En el 99.999% de los casos nada malo saldrá de eso.
Personalmente, soy reacio a usar estos para cualquier cosa que no sean los mensajes de depuración. Lo he hecho, pero trato de no mostrar ese tipo de información a los clientes o usuarios finales. Mis clientes no son ingenieros y a veces no son expertos en informática. Podría registrar esta información en la consola, pero, como dije, de mala gana a excepción de compilaciones de depuración o herramientas internas. Supongo que sí depende de la base de clientes que tengas.
__FUNCTION__
no es estándar, __func__
existe en C99 / C ++ 11. Los otros ( __LINE__
y __FILE__
) están bien.
Siempre informará el archivo y la línea correctos (y funcionará si elige usar __FUNCTION__
/ __func__
). La optimización no es un factor, ya que es una expansión de macros en tiempo de compilación; nunca afectará el rendimiento de ninguna manera.