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.
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.