c++ - Deshabilitar la eliminación "if(0)" en gcc
gcc c (2)
¿Cómo puedo evitar que GCC elimine el código dentro de (0) bloque?
Cuando uso Visual Studio, una de mis técnicas de depuración es poner un código como este en mi programa:
if (0)
do_some_debug_printing_and_checking();
Luego, cuando se alcanza un punto de interrupción, hago clic en la línea do_some_debug_printing_and_checking () , selecciono "establecer la siguiente declaración" y la obligo a ejecutarse.
Cuando uso gcc / gdb como back-end, el "set next statement" ya no funciona, ya que GCC simplemente elimina el código dentro de la sentencia if (0) .
Por supuesto, estoy usando la marca -O0 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 muerto, pero no tiene ningún efecto: el contenido de if (0) simplemente no está presente en el archivo binario y no puedo usar set next declaración para saltar en ella.
¿Hay alguna buena manera de decirle a gcc que inhabilite la eliminación de los contenidos if (0) ?
Editar:
Gracias por la solución "variable adicional", sin embargo, hay dos cosas que no me gustan:
- Sigue siendo una línea extra de código.
- No se optimizará automáticamente cuando compile la versión de lanzamiento y quiero que desaparezcan esos elementos de depuración. Seguramente puedo usar # ifdef-s, pero eso es aún más líneas adicionales.
Realmente, ¿no hay absolutamente ninguna opción para que GCC mantenga ese código muerto?
Lo más sencillo es hacer que la verificación dependa de (digamos) una variable con enlace externo.
P.ej
extern bool debug;
if (debug)
do_some_debug_printing_and_checking();
El lugar en el ámbito del espacio de nombres:
bool debug = false;
No confiaría en las banderas del compilador gcc para hacer esto. Las banderas del compilador pueden cambiar a través de las versiones de gcc, y cambian a través de los compiladores. Puede que necesite depurar el mismo código en seis meses en Visual C ++ ...
@CharlesBailey hace una buena sugerencia sobre cómo hacer esto con una variable extern
. Aquí hay una alternativa que no requiere que una variable esté expuesta a todo el módulo o que se mantenga en almacenamiento estático.
Declare una variable temporal volatile
en el alcance de la declaració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 ni optimice la rama.
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 salga. Tanto este enfoque como el extern
deben funcionar, pero tienen compensaciones ligeramente diferentes (y probablemente insignificantes).
Si está dispuesto a usar macros para ayudar a resolver este problema, puede deshabilitar fácilmente la variable temporal cuando libere 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
Luego declara tu declaración if
:
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 mantiene. Cuando define IS_DEBUGGING como 0, la macro se expande a la constante false
y el compilador optimiza la rama. También se podría hacer algo muy similar para el enfoque extern
.
Estas pocas líneas de código adicionales, pero son independientes de la cantidad de veces que usas TMP_DBG_FLAG. El código también es mucho más legible que usar toneladas de ifdef
s. La macro podría hacerse un poco más segura (agregándole el valor de __LINE__
), 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