Si codifica en C, Objective-C o C ++, puede usar el CLang Static Analyzer para criticar su fuente sin realmente ejecutandolo.
Hay algunas herramientas de depuración de memoria disponibles: ValGrind, Guard Malloc en Mac OS X, Electric Fence en * NIX.
Algunos entornos de desarrollo ofrecen la opción de usar un asignador de memoria de depuración, que hace cosas como rellenar las páginas recién asignadas y las páginas recién liberadas con basura, detectar la liberación de punteros no asignados y escribir algunos datos antes y después de cada bloque de montón, con se llama al depurador si el patrón conocido de esos datos cambia alguna vez.
Un tipo en Slashdot dijo que obtuvo mucho valor de una sola vez nueva línea de fuente en un depurador. "Eso es todo" dijo. No siempre sigo su consejo, pero cuando lo tengo me ha sido muy útil. Incluso si no tiene un caso de prueba que estimule una ruta de código poco común, puede girar una variable en su depurador para tomar dichas rutas, por ejemplo, asignando algo de memoria y luego utilizando el depurador para establecer su nuevo puntero en NULL en lugar de dirección de memoria, luego pasar por el controlador de errores de asignación.
Utilizar aserciones: la macro assert () en C, C ++ y Objective-C. Si su idioma no proporciona una función de afirmación, escríbala usted mismo.
Use afirmaciones generosamente, luego déjelas en su código. Llamo a assert () "La prueba que sigue probando". Los uso con más frecuencia para verificar las condiciones previas en el punto de entrada de la mayoría de mis funciones. Esa es una parte de "Programación por contrato", que está incorporada en el lenguaje de programación de Eiffel. La otra parte es postcondiciones, es decir, usar assert () en los puntos de retorno de la función, pero me parece que no obtengo tanto kilometraje como precondiciones.
También puede usar aserción para verificar invariantes de clase. Si bien no se requiere estrictamente que ninguna clase tenga invariable, las clases más sensiblemente diseñadas las tienen. Una clase invariante es una condición que siempre es verdadera, excepto dentro de las funciones miembro, que podrían colocar temporalmente su objeto en un estado inconsistente. Tales funciones siempre deben restaurar la consistencia antes de regresar.
Por lo tanto, cada función miembro podría verificar el invariante al ingresar y salir, y la clase podría definir una función llamada CheckInvariant que cualquier otro código podría llamar en cualquier momento.
Use una herramienta de cobertura de código para verificar qué líneas de su fuente realmente se están probando, luego diseñe pruebas que estimulen las líneas no probadas. Por ejemplo, puede verificar los manejadores de poca memoria ejecutando su aplicación dentro de una VM que está configurada con poca memoria física, y no con un archivo de intercambio o uno muy pequeño.
(Por alguna razón, nunca tuve conocimiento de ello, aunque el BeOS podía ejecutarse sin un archivo de intercambio, era muy inestable de esa manera. Dominic Giampaolo, quien escribió el sistema de archivos BFS, me instó a que nunca ejecutara el BeOS sin intercambio. no veo por qué eso debería importar, pero debe haber sido algún tipo de artefacto de implementación.)
También debe probar la respuesta de su código a los errores de E / S. Intente almacenar todos sus archivos en un recurso compartido de red, luego desconecte el cable de red mientras su aplicación tiene una gran carga de trabajo. De manera similar, desconecte el cable, o apague su red inalámbrica, si se está comunicando a través de una red.
Una cosa que me resulta particularmente irritante son los sitios web que no tienen un código Javascript robusto. Las páginas de Facebook cargan docenas de pequeños archivos de Javascript, pero si alguno de ellos no se descarga, la página se rompe. Solo tiene que haber alguna forma, ya sea para proporcionar cierta tolerancia a fallos, por ejemplo, volviendo a intentar una descarga, o para proporcionar algún tipo de respuesta razonable cuando algunos de sus scripts no se descargaron.
Intente matar su aplicación con el depurador o con "kill -9" en * NIX mientras está en medio de escribir un archivo grande e importante. Si su aplicación está bien diseñada, todo el archivo se escribirá o no se escribirá en absoluto, o tal vez si solo está escrito parcialmente, lo que se escribe no se corromperá, y los datos guardados serán completamente utilizables por la aplicación al volver a leer el archivo.
Las bases de datos
siempre tienen E / S de disco tolerante a fallos, pero casi ningún otro tipo de aplicación lo tiene. Si bien los sistemas de archivos registrados por diario evitan la corrupción del sistema de archivos en caso de falla de energía o fallas, no hacen nada para evitar la corrupción o la pérdida de datos del usuario final. Esa es la responsabilidad de las aplicaciones de usuario, pero casi ninguna otra que las bases de datos implementa la tolerancia a fallos.