3.3. Técnicas de depuración

La mejor costumbre para eliminar fallos es usar aserciones como se explica al principio de este capítulo; haciendo esto le ayudará a encontrar errores lógicos antes de que causen problemas reales. Esta sección contiene otros consejos y técnicas que podrían ayudar durante la depuración.

3.3.1. Macros de seguimiento

Algunas veces es útil imprimir el código de cada sentencia cuando es ejecutada, o cout o trazar un fichero. Aquí esta una macro de preprocesaor para llevar a cabo esto:

#define TRACE(ARG) cout << #ARG << endl; ARG

Ahora puede ir a través y alrededor de las sentencias que traceé con esta macro. Sin embargo, esto puede introducir problemas. Por ejemplo, si coge la sentencia:

for(int i = 0; i < 100; i++) cout << i << endl;

y ponga ambas líneas dentro de la macro TRACE( ), obtiene esto:

TRACE(for(int i = 0; i < 100; i++)) TRACE( cout << i << endl;)

que se expande a esto:

cout << "for(int i = 0; i < 100; i++)" << endl; for(int i = 0; i < 100; i++) cout << "cout << i << endl;" << endl; cout << i << endl;

que no es exactamente lo que quiere. Por lo tanto, debe usar esta técnica cuidadosamente.

Lo siguiente es una variación en la macro TRACE( ):

#define D(a) cout << #a "=[" << a << "]" << endl;

Si quiere mostrar una expresión, simplemente póngala dentro de una llamada a D( ). La expresión se muestra, seguida de su valor ( asumiendo que hay un operador sobrecargado << para el tipo de resultado). Por ejemplo, puede decir D(a + b). Puede usar esta macro en cualquier momento que quiera comprobar un valor intermedio.

Estas dos macros representan las dos cosas fundamentales que hace con un depurador: trazar la ejecución de código y mostrar valores. Un buen depurador es una herramienta de productividad excelente, pero a veces los depuradores no están disponibles, o no es conveniente usarlos. Estas técnicas siempre funcionan, sin tener en cuenta la situación.