2010-03-24 13 views
8

Durante el modo de depuración o mientras estoy haciendo la prueba, tengo que imprimir una gran cantidad de información diversa, así que utilice este método:cómo separar la depuración y el modo de liberación de código

#ifdef TESTING 
// code with lots of debugging info 
#else 
// clean code only 
#endif // TESTING` 

Es este un buen método o ¿Hay algún otro método simple y elegante?

Pero de esta manera, estoy repitiendo el mismo código en dos lugares y si algo va a cambiar más adelante en el código, tengo que hacerlo en ambos lugares, lo que consume mucho tiempo y es propenso a errores.

Gracias.

Estoy usando MS Visual Studio.

Respuesta

17

Puede usar una macro para imprimir información de depuración y luego en la compilación de lanzamiento, defina esa macro como vacía.

por ejemplo,

#ifdef _DEBUG 
#define DEBUG_PRINT(x) printf(x); 
#else 
#define DEBUG_PRINT(x) 
#endif 

Usando este método, también se puede añadir más información como

__LINE__ 
__FILE__ 

a la información de depuración de forma automática.

+1

Las macros son mal estilo C++. –

+0

Tal vez, pero la pregunta fue etiquetada tanto C como C++. –

+0

No estoy de acuerdo con Alexey, escribo años con C++ y Macros sin ningún problema. Tal vez sea un mal estilo de C++, para los programadores malos que no saben lo que hacen, pero solo con macros puedo hacer algunas reflexiones muy difíciles. La libertad de usar muchas formas no es tan mala :) – Aristos

2

Utilice un definir así en incluir encabezados

#ifdef TESTING 
#define DEBUG_INFOS(_X_) CallYourDebugFunction(_X_) 
#else 
#define DEBUG_INFOS(_X_) ((void)0) 
#endif 

y luego utilizar solamente esto en su código

... 
DEBUG_INFOS("infos what ever"); 
RestOfWork(); 
... 

También puede utilizar y la búsqueda de la ASSERT y TRACE macros y use el DebugView de sysinternals para leer el tiempo real de salida del rastreo, o rastrear problemas con ASSERT. ASSERT y TRACE hacen un trabajo similar, y puedes obtener ideas de ellos.

comentarios: utilizo la declaración de PRUEBA, porque veo eso en la pregunta.

5

escribir una vez

#ifdef _DEBUG 
const bool is_debig = true; 
#else 
const bool is_debig = false; 
#endif 

y luego

template<bool debug> 
struct TemplateDebugHelper { 
    void PrintDebugInfo(const char*); 
    void CalcTime(...); 
    void OutputInfoToFile(...); 
    /// ..... 
}; 

// Empty inline specialization 
template<> 
struct TemplateDebugHelper<false> { 
    void PrintDebugInfo(const char*) {} // Empty body 
    void CalcTime(...) {} // Empty body 
    void OutputInfoToFile(...) {} // Empty body 
    /// ..... 
}; 

typedef TemplateDebugHelper<is_debug> DebugHelper; 

DebugHelper global_debug_helper; 

int main() 
{ 
    global_debug_helper.PrintDebugInfo("Info"); // Works only for is_debug=true 
} 
+0

¿Puedo preguntar si esto dejó algún código en los archivos compilados, en el modo de lanzamiento? – Aristos

+0

En el peor de los casos, lo hará frijol función vacía cal. Sin embargo, dado que el código debe estar disponible para el compilador, según mi experiencia, incluso eso se optimiza. –

+1

Me gusta esta respuesta, excepto que mi experiencia es que si un programador tiene que escribir 'global_debug_helper.PrintDebugInfo' no se va a molestar. Generalmente uso short tops para que sean fáciles de escribir, pero fáciles de detectar: ​​ BUG.OUT ("Info"); – swestrup

1

Usted podría utilizar algo como nivel de gravedad boost::log ajuste para el que necesita.

void init() 
{ 
    logging::core::get()->set_filter 
    (
     flt::attr<logging::trivial::severity_level>("Severity") >= logging::trivial::info 
    ); 
} 

int main(int, char*[]) 
{ 
    init(); 

    BOOST_LOG_TRIVIAL(trace) << "A trace severity message"; 
    BOOST_LOG_TRIVIAL(debug) << "A debug severity message"; 
    BOOST_LOG_TRIVIAL(info) << "An informational severity message"; 
    BOOST_LOG_TRIVIAL(warning) << "A warning severity message"; 
    BOOST_LOG_TRIVIAL(error) << "An error severity message"; 
    BOOST_LOG_TRIVIAL(fatal) << "A fatal severity message"; 
} 

Creo que también tenemos algo similar.

2

Use Log4Cxx, en lugar de hacer su propio registro. El paquete Log4Cxx es altamente configurable, admite diferentes niveles de registro según la importancia/gravedad y admite múltiples formas de salida.

Además, a menos que sea un código muy crítico que debe ser súper optimizado, recomendaría dejar las declaraciones de registro (suponiendo que use Log4Cxx) en su código, pero simplemente baje el nivel de registro.De esta forma, el registro se puede habilitar dinámicamente, lo que puede ser increíblemente útil si uno de tus usuarios experimenta un error difícil de replicar ... solo dirígelos sobre cómo configurar un nivel de registro más alto. Si elimina completamente el registro desde el ejecutable, entonces no hay forma de obtener ese valioso resultado de depuración en el campo.

+1

Esto. En el proyecto de mi equipo, descubrimos que compilar en los mensajes de TRACE no tenía un impacto notorio en el rendimiento a menos que permitamos el rastreo, y la belleza de los marcos log4xxx es que puedes hacerlo para algunas fuentes de registro pero no para otras, dependiendo sobre lo que intentas atacar Hay algunos lugares en nuestro código donde los argumentos para la llamada al registro de seguimiento son costosos de computar; para estos, simplemente llamamos a Logger :: isEnabledFor (LogLevelTrace) para detectar cuando el seguimiento está activado para un registrador dado; si es así, construimos los args caros y registramos el mensaje de seguimiento, de lo contrario lo dejamos en paz. – anelson

+0

@anelson, ¿por qué no usaste LOG4CXX_TRACE (LOGGER, MSG)? Creo que el macro ya lo hace por ti. –

0

estoy escribiendo para sistemas embebidos en C. En mis programas que estoy usando macros siguientes:

 
#define _L log_stamp(__FILE__, __LINE__) 

#define _LS(a) log_string(a) 

#define _LI(a) log_long(a) 

#define _LA(a,l) log_array(a,l) 

#define _LH(a) log_hex(a) 

#define _LC(a) log_char(a) 

#define ASSERT(con) log_assert(__FILE__, __LINE__, con) 

cuando estoy haciendo versión de lanzamiento, simplemente apagar la directiva #define DEBUG y todas las macros se vuelven vacías Tenga en cuenta que no consume ningún ciclo de CPU y memoria en la versión de lanzamiento. Las macros son la única forma de guardar información de registro: donde se realizó el registro (número de archivo y línea).

Si necesito esta información que utilizo: _L;_LS("this is a log message number ");_LI(5);

de otra manera sin _L Directiva.

0

Hay una manera simple, que funciona con la mayoría de los compiladores:

#ifdef TESTING 
    #define DPRINTF(args)  printf args 
#else 
    #define DPRINTF(args)  ((void)0) 
#endif 

A continuación, en el código fuente que se debe utilizar como:

DPRINTF(("Debug: value a = %d, value b = %d\n", a, b)); 

El inconveniente es que tienes que usar doble paréntesis, pero en las antiguas C y C++ no se admiten los estándares de macro variadic (solo como una extensión de compilación).

Cuestiones relacionadas