Si codifica en C, Objective-C o C ++, puede usar el Analizador estático CLang para criticar su fuente sin ejecutarlo realmente.
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 llenar páginas recién asignadas y 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, siendo el depurador se llama si el patrón conocido de esos datos cambia alguna vez.
Un tipo en Slashdot dijo que obtuvo mucho valor de la nueva línea de fuente de un solo paso 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 tales rutas, por ejemplo, asignando algo de memoria, luego usando el depurador para establecer su nuevo puntero en NULL en lugar de dirección de memoria, luego recorriendo el controlador de fallas de asignación.
Utilice aserciones: la macro afirmar () en C, C ++ y Objective-C. Si su idioma no proporciona una función de aserción, escríbala usted mismo.
Use afirmaciones generosamente, luego déjelas en su código. Llamo afirmar () "La prueba que sigue probando". Los uso con mayor 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á integrada en el lenguaje de programación de Eiffel. La otra parte son las condiciones posteriores, es decir, el uso de afirmar () en los puntos de retorno de la función, pero encuentro que no obtengo tanto kilometraje de eso como las condiciones previas.
También puede usar afirmar para verificar invariantes de clase. Si bien no se requiere estrictamente que ninguna clase tenga invariantes, la mayoría de las clases diseñadas con sensatez las tienen. Una clase invariante es una condición que siempre es cierta, aparte de dentro de las funciones miembro que pueden colocar temporalmente su objeto en un estado inconsistente. Tales funciones siempre deben restaurar la consistencia antes de que regresen.
Por lo tanto, cada función miembro podría verificar la invariante al entrar 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 controladores de poca memoria ejecutando su aplicación dentro de una VM configurada con poca memoria física, y sin archivos de intercambio o muy pequeña.
(Por alguna razón, nunca tuve acceso, 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 lo hago vea 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 su cable de red mientras su aplicación tiene una gran carga de trabajo. Del mismo modo, desconecte el cable, o apague la conexión inalámbrica, si se está comunicando a través de una red.
Una cosa que encuentro 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 Javascript, pero si alguno de ellos no se descarga, la página entera se rompe. Simplemente tiene que haber alguna forma de proporcionar cierta tolerancia a fallas, por ejemplo, al volver a intentar una descarga, o para proporcionar algún tipo de respaldo razonable cuando algunos de sus scripts no se descargaron.
Intente eliminar su aplicación con el depurador o con "kill -9" en * NIX mientras está escribiendo 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 se escribe parcialmente, lo que se escribe no se corromperá, y los datos que se guardan serán completamente utilizables por la aplicación al volver a leer el archivo.
las bases de datos siempre tienen E / S de disco con tolerancia a fallas, pero casi ningún otro tipo de aplicación lo hace. Si bien los sistemas de archivos registrados 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 del usuario, pero casi ninguna otra que las bases de datos implementan tolerancia a fallas.