2012-07-01 9 views
18

¿Cómo puedo evitar que GCC elimine el código dentro de si (0) bloque?Deshabilitar "if (0)" eliminación en gcc

Cuando uso de Visual Studio, una de mis técnicas de depuración es poner un código como éste en mi programa:

if (0) 
    do_some_debug_printing_and_checking(); 

Entonces, cuando se alcanzó un punto de interrupción, hago clic en el do_some_debug_printing_and_checking() línea , seleccione "establecer declaración siguiente" y forzarlo a ejecutar.

Cuando uso gcc/gdb como back-end, la "declaración set next" ya no funciona, ya que GCC simplemente elimina el código de if (0).

Por supuesto, estoy usando el -0 para deshabilitar la optimización. También probé los indicadores -fno-dce -fno-tree-dce para desactivar explícitamente la eliminación del código inactivo, pero no tiene ningún efecto: el contenido de if (0) simplemente no está presente en el archivo binario y yo no puede usar establecer la siguiente instrucción para saltar a ella.

¿Hay alguna buena manera de decirle a gcc que deshabilite la eliminación de si (0) contenido?

Editar:

Gracias por la solución "variable adicional", sin embargo, hay 2 cosas que no me gustan de él:

  1. sigue siendo una línea adicional de código
  2. Ganó No se optimiza automáticamente cuando construyo la versión de lanzamiento y quiero que esas cosas de depuración desaparezcan. Seguramente puedo usar # ifdef-s, pero eso es aún más líneas adicionales.

Realmente, no hay absolutamente ninguna opción para hacer que GCC conserve ese código muerto?

+1

Sé que esto no es lo que pedían, pero tratar utilizando una variable global establecida en falso para su ifs. De esa forma, el compilador no optimizará tus declaraciones if. –

+12

¿Por qué no simplemente 'llamas a do_some_debug_printing_and_checking() 'en gdb cuando quieres ejecutar esa función? – Mat

Respuesta

12

Lo más simple es hacer que la comprobación dependa de (por ejemplo) una variable con enlace externo.

E.g.

extern bool debug; 
if (debug) 
    do_some_debug_printing_and_checking(); 

en algún lugar en el ámbito del espacio de nombres:

bool debug = false; 
+5

Me gustaría dejar un 'volátil' allí. – Kos

+0

@Kos: ¿Por qué harías eso? –

+0

para que el compilador no suponga que el valor de la variable no cambió entre dos puntos – Kos

8

yo no depender de parámetros del compilador gcc para hacer esto. Los indicadores del compilador pueden cambiar en todas las versiones de gcc y cambian en los compiladores. Puede encontrar que necesita depurar el mismo código en seis meses en Visual C++ ...

@CharlesBailey hace una buena sugerencia de cómo hacer esto con una variable extern. Aquí hay una alternativa que no requiere que una variable se exponga a todo el módulo o que se guarde en un almacenamiento estático.

declarar una variable temporal volatile en el ámbito de la instrucción if:

if (volatile bool dbg = false) 
{ 
    do_some_debug_printing_and_checking(); 
} 

Esto mantiene el alcance de la variable temporal bastante estrecho. El calificador volatile no permite que el compilador asuma nada sobre la variable u optimice la bifurcación.

Una cosa a tener en cuenta es que la variable siempre se asigna en la pila, y se mantendrá en la pila hasta que la función finalice. Tanto este enfoque como el enfoque extern deberían funcionar, pero tienen intercambios ligeramente diferentes (y probablemente insignificantes).

Si usted está dispuesto a utilizar macros para ayudar a resolver este problema, entonces se puede desactivar fácilmente la variable temporal cuando su comunicado su código en producción:

#ifndef IS_DEBUGGING 
# define IS_DEBUGGING 0 
#endif 

#if IS_DEBUGGING 
# define TMP_DBG_FLAG volatile bool dbg_flag = false 
#else 
# define TMP_DBG_FLAG false 
#endif 

Entonces declarar su estado de if como:

if (TMP_DBG_FLAG) 
{ 
    do_some_debug_printing_and_checking(); 
} 

Cuando define IS_DEBUGGING como 1, la variable local se crea, se declara volátil y se guarda. Cuando define IS_DEBUGGING como 0, la macro se expande a la constante false y el compilador optimiza la bifurcación. Algo muy similar podría hacerse para el enfoque extern, también.

Estas líneas adicionales de código, pero son independientes del número de veces que usa TMP_DBG_FLAG. El código también es mucho más legible que el uso de toneladas de ifdef s. La macro se podría hacer un poco más seguro (añadiendo el valor de __LINE__ a ella), pero esto requeriría tres macros, y probablemente no sea necesario:

#if IS_DEBUGGING 
// paste symbols 'x' and 'y' together 
# define TMP_DBG_FLAG_SYMCAT0(x,y) x ## y 

// need one level of indirection to expand __LINE__... 
# define TMP_DBG_FLAG_SYMCAT(x,y) TMP_DBG_FLAG_SYMCAT0(x,y) 

# define TMP_DBG_FLAG volatile bool TMP_DBG_FLAG_SYMCAT(dbg_flag_,__LINE__) = false 
#else 
# define TMP_DBG_FLAG false 
#endif 
Cuestiones relacionadas