Aprende tu depurador
Es realmente útil familiarizarse con el depurador, ya sea basado en texto, IDE completo o alguna combinación de los mismos. No das muchos detalles, así que describiré el caso general:
1) puntos de interrupción
Además de detenerse en una línea de código, muchos depuradores le permiten especificar que se rompa cuando surge una condición (por ejemplo, "x> 5"), después de varias pasadas a través del código o cuando alguna memoria cambia el valor. Esto es muy útil para comprender cómo su código entra en un mal estado, por ejemplo, observar cuándo un puntero se vuelve nulo en lugar de detectar el bloqueo cuando se desreferencia.
2) Pasando por el código
Puede ingresar a las funciones, línea por línea a lo largo del código, saltar sobre las líneas ('establecer la siguiente declaración') y luego 'subir' fuera de las funciones. Es una forma realmente poderosa de seguir la ejecución de su código para verificar que hace lo que cree que hace :-)
3) Evaluar expresiones
Por lo tanto, puede colocar variables en una lista / ventana de Observación y ver su cambio de valor cuando alcanza un punto de interrupción o atraviesa el código, pero también puede hacer evaluaciones de expresiones complejas, por ejemplo, se evaluará "x + y / 5". Algunos depuradores también le permiten poner llamadas a funciones en las listas de vigilancia. Puede hacer cosas como "time ()", "MyFunction (...)", "time ()" y obtener la temporización del tiempo que tardó su función.
4) Excepciones y manejo de señales
Entonces, si su idioma admite excepciones y / o señales, generalmente puede configurar el depurador para saber cómo reaccionar ante esto. Algunos depuradores le permiten entrar en el código en el punto donde la excepción está por suceder, en lugar de después de que no se haya detectado. Esto es útil para rastrear problemas extraños como errores de "Archivo no encontrado" porque el programa se ejecuta como una cuenta de usuario diferente.
5) Adjuntar a un proceso / núcleo
Entonces, a veces tiene que usar el depurador para saltar a un proceso existente que está yendo mal. Si tiene el código fuente cerca y los símbolos de depuración están intactos, puede sumergirse como si hubiera comenzado en el depurador en primer lugar. Esto también es similar para los volcados de núcleo, excepto que generalmente no puede continuar la depuración en esos (el proceso ya ha muerto).
Configuración de compilación
Hay varias variaciones de compilación que puede realizar activando o desactivando funciones como símbolos de depuración, optimizaciones y otros indicadores del compilador:
1) Depuración
Tradicionalmente, esta es una compilación simple sin características especiales, lo que hace que sea fácil de depurar y predecible. Varía un poco según la plataforma, pero puede haber algo de margen adicional, por ejemplo, asignaciones y tamaños de búfer para garantizar la fiabilidad. Por lo general, estará presente un símbolo de compilador como DEBUG o Conditional ("Debug") para que se introduzca el código específico de depuración. Esta es a menudo la compilación que se envía, con símbolos de nivel de función intactos, especialmente si la confiabilidad y / o la repetibilidad son preocupación.
2) Lanzamiento / construcción optimizada
La habilitación de las optimizaciones del compilador permite que algunas instalaciones de generación de código de bajo nivel en el compilador hagan un código más rápido o más pequeño basado en suposiciones sobre su código. Los aumentos de velocidad posibles son irrelevantes si la elección de su algoritmo es deficiente, pero para los cálculos intensivos esto puede marcar una gran diferencia a través de la eliminación de subexpresión común y el desenrollado de bucle, etc. A veces, las suposiciones hechas por el optimizador son incompatibles con su código, por lo que tiene que ser reducido una muesca. Los errores del compilador en el código optimizado también han sido un problema en el pasado.
3) Construcción instrumentada / perfilada
Su código está construido con un código de instrumentación específico para medir la cantidad de veces que se llama a una función y cuánto tiempo se pasa en esa función. Este código generado por el compilador se escribe al final del proceso para su análisis. A veces es más fácil usar una herramienta de software especializada para esto, ver más abajo. Este tipo de compilación nunca se envía.
4) Construcción segura / comprobada
Todas las 'válvulas de seguridad' se habilitan mediante símbolos de preprocesador o configuraciones del compilador. Por ejemplo, los parámetros de la función de verificación de macros ASSERT, los iteradores verifican las colecciones no modificadas, los canarios se colocan en la pila para detectar la corrupción, las asignaciones del montón se llenan con valores centinela (0xdeadbeef es memorable) para detectar la corrupción del montón. Para los clientes que tienen problemas persistentes que solo pueden reproducirse en su sitio, es algo útil.
5) Construcción de características
Si tiene diferentes clientes que tienen diferentes requisitos de su producto de software, es común hacer una compilación para cada cliente que ejercite las diferentes partes durante la prueba. Por ejemplo, un cliente quiere la funcionalidad sin conexión y otro quiere solo en línea. Es importante probar en ambos sentidos si el código se construye de manera diferente.
Registro y rastreo
Así que hay que escribir algunas declaraciones útiles para printf () y luego hay que escribir información de rastreo integral y estructurada en los archivos de datos a medida que avanza. Esta información se puede extraer para comprender el comportamiento / características de tiempo de ejecución de su software. Si su código no falla, o si toma algún tiempo reprobarlo, es útil tener una imagen de, por ejemplo, una lista de subprocesos, sus transiciones de estado, asignaciones de memoria, tamaños de grupo, memoria libre, número de identificadores de archivos, etc. realmente depende del tamaño, la complejidad y los requisitos de rendimiento de su aplicación, pero como ejemplo, los desarrolladores de juegos quieren asegurarse de que no haya "picos" en el uso de CPU o memoria mientras un juego está en progreso, ya que eso probablemente afectará la velocidad de fotogramas. El sistema mantiene parte de esta información, algunas las bibliotecas y el resto el código.
Otras herramientas
No siempre es necesario crear una compilación diferente para cubrir estos escenarios: se pueden elegir algunos aspectos en tiempo de ejecución a través de la configuración del proceso (trucos del Registro de Windows), haciendo que las bibliotecas alternativas estén disponibles con mayor prioridad que las bibliotecas estándar, por ejemplo, en su ruta del cargador o utilizando un software ICE o un depurador especializado para sondear su software en busca de características de tiempo de ejecución (por ejemplo, Intel v-Tune). Algunos de estos cuestan mucho dinero, algunos son herramientas de código libre, Xtrace.