2009-02-27 20 views
114

Suponiendo que el compilador de C++ compatible con ellas, ¿hay alguna razón en particular no utilizar __FILE__, __LINE__ y __FUNCTION__ para propósitos de registro y depuración?__FILE__, __LINE__, y el uso __FUNCTION__ en C++

Me preocupa principalmente 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, como resultado, obtener un resultado de rendimiento.

Básicamente, puedo confiar en __FILE__, __LINE__ y __FUNCTION__-siempre hacer lo correcto?

+0

__LINE__ debe hacer lo correcto. Lo he usado ampliamente y sus cohortes, incluyendo __PRETTY_FUNCTION__. ... Pero ... bueno, ahora mismo estoy mirando el código donde se encuentra __LINE__. Probablemente porque está en un bloque de captura para el manejo de excepción de try/catch. –

+2

relevante: [referencia de gcc para macros predefinidas] (http://gcc.gnu.org/onlinedocs/cpp/Standard-Predefined-Macros.html) –

Respuesta

140

__FUNCTION__ no es estándar, __func__ existe en C99/C++ 11. Los demás (__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; será nunca rendimiento del efecto de ninguna manera.

+2

'__func__' es un problema en C++. C99 no dice una palabra sobre los argumentos predeterminados, etc., donde no es tan obvio cómo se debe comportar '__func__' en C++. – wilhelmtell

+3

@thr: mientras haces un buen punto. Estaba bastante claro que '__func__' existe en c99, no en C++. De todos modos, creo que una implementación razonable de '__func__' en C++ solo resultaría en el nombre destrozado. Como no soy un escritor de compilación, no es realmente mi llamado. –

+0

¿Qué compiladores no admiten '__FUNCTION__' en absoluto? ¿Qué compiladores, excepto gcc recientes, tratan esto como una variable, no como una macro? – basin

7

Personalmente, soy reacio a utilizar 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.

+21

"Podría registrar esta información en la consola" - o mejor aún: inicie sesión en un archivo para que, si algo sale mal, le pida al cliente que se lo envíe ... – Christoph

30

En casos excepcionales, 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 comienzan con __LINE__ 100. Se pueden añadir opcionalmente un nuevo nombre de archivo

#line 100 "file.c" 

Es útil sólo en raras ocasiones. 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. El uso de la biblioteca impulso preprocesador, se puede incrementar la línea actual en un 50:

#line BOOST_PP_ADD(__LINE__, 50) 

pensé que es útil mencionar que, ya que preguntas sobre el uso de __LINE__ y __FILE__. Uno nunca se lo suficientemente sorpresas fuera de C++ :)

Editar: @ Jonathan Leffler ofrece algunos más buenos casos de uso en los comentarios:

ensuciar con #line es muy útil para los pre-procesadores que desea 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.

22

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.

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

Es bueno saber sobre el \ _ \ _ PRETTY_FUNCTION \ _ \ _. ¡Muy útil! – Maverobot

4

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.

+0

Buen punto para que aparezca. Es trivial extraer esta información usando la utilidad 'strings' para extraer todos los datos de cadena del ejecutable. Incluso los ejecutables comprimidos se pueden extraer. Sea muy consciente de lo que envía a un sitio del cliente. Muchas veces los competidores pueden tener sus manos en sus ejecutables, aunque se supone que no deben hacerlo. – Marty

Cuestiones relacionadas