2011-08-22 9 views
5

Actualmente me estoy enfrentando a uno de los errores más perversos que he enfrentado en un proyecto grande y complejo en el que mi equipo está trabajando. Estamos utilizando C++ como lenguaje de programación, y actualmente Visual Studio para desarrollo, aunque el producto final está destinado a ejecutarse multiplataforma.Describiendo y encontrando un error que corrompe el estado que causa fallas aparentemente aleatorias

El error:

Hay un error en nuestro sistema que provoca accidentes en puntos aparentemente aleatorios de ejecución. Las causas de bloqueo generalmente son violaciones de acceso de lectura de direcciones que cambian cada vez que se ejecuta el programa. A veces obtenemos errores de corrupción de montón también. Las pilas de llamadas nos llevan a puntos variables en nuestra base de código, y raramente a algunas bibliotecas externas (Lua en nuestro caso), donde el error claramente no miente.

Parece que este error se ha estado desarrollando durante los últimos 4 meses. Esa cantidad de tiempo atrás, más o menos, algunos de los miembros de mi equipo vieron cómo el programa frontend fallaba en maneras y ubicaciones muy similares a lo que sucede ahora.

Algunos detalles más:

Nuestro código base es aproximadamente 800K líneas de C++ puro (excluidos los comentarios) grande, y se desarrolló a lo largo de 3 años. El proyecto actual pesa aproximadamente 300K. Hemos utilizado pruebas unitarias excesivas y otras formas de eliminar errores antes de que sucedan, como afirmaciones, punteros inteligentes, etc.

Los otros y yo hemos estado tratando de encontrar este error (s) por más de 2 semanas. Se está convirtiendo en algo más que una pesadilla para mí. En un proyecto tan complejo, incluso la buena depuración del viejo archivo de impresión parece fallar debido a la complejidad que ahora tiene.

Mis preguntas

  • ¿Qué tipo de error nos enfrentamos aquí? ¿Hay incluso un nombre para esto? ¿Este tipo de error ocurre más o menos a menudo en otros proyectos grandes?

  • ¿Qué podemos hacer para encontrarlo y eliminarlo después de haber pasado 2 semanas de depuración infructuosa usando varias utilidades, en varias plataformas y con varias configuraciones de compilación?

(Mi pregunta anterior estaba cerrado, así que estoy tratando de formular mejor y con más detalles en esta ocasión, enlace: https://stackoverflow.com/questions/7154645/how-is-this-kind-of-bug-called)

+0

Arf, los errores esporádicos son los peores. Es hora de aprender a usar herramientas de depuración. –

Respuesta

8

Los síntomas que usted describe son típicas de daños en el montón (no ¡todas las corrupciones de montón se informan como tales con un mensaje de error!). Necesitará auditar el tiempo de vida de todos los objetos en su programa; asegúrate de no estar liberando las cosas dos veces, o utilizándolas después de liberarlas, y asegúrate de no desbordar ningún búfer. Es posible que desee aprovechar esta oportunidad para usar cosas como std::smart_ptr (o boost::smart_ptr) para automatizar partes de su gestión de almacenamiento dinámico.

Si está usando Linux o Mac OS, intente ejecutar su programa bajo valgrind - detectará muchos errores de corrupción de pila y pila. En Windows, use el application verifier; puede ayudar a que los errores causen un colapso más cercano al punto en que realmente ocurrieron.

Si está utilizando subprocesos, una condición de carrera que conduce a la corrupción de montón es otra posibilidad. Audite sus mecanismos de bloqueo también.

Si puede reproducir fácilmente este error y tener un sistema de control de origen en su lugar, considere una bisección para determinar exactamente cuándo se introdujo también. Es decir, realice una búsqueda binaria en el historial del código fuente para encontrar el primer compromiso con el error. Git tiene una herramienta para hacer esto automáticamente - git-bisect - puedes importar una copia de tu repositorio en git para ejecutar esta herramienta si no estás usando git ya.

Además, vea si puede deshabilitar partes de su programa (evite que se invoque el código en cuestión) en un intento de reducir el problema. Tenga en cuenta que esto puede tener falsos positivos: si deshabilita el módulo X y deja de bloquearse, podría significar que el módulo X está dañando el montón, o podría significar que el módulo W corrompió el montón y que el módulo X es bueno para darse cuenta .

+1

Muy buenos puntos. Aunque tenga en cuenta que los errores esporádicos bisectantes son * muy * difíciles. – Owen

+0

@Owen, de ahí el "si se puede reproducir fácilmente" ...:/ – bdonlan

+0

Ah cierto que se perdió eso. – Owen

0

Simplemente complementando la excelente respuesta de Bdonlan: ya que está desarrollando código para Windows y trabajando con grandes proyectos, le recomiendo que compre el libro "Advanced Windows Debugging" y se familiarice con WinDbg, AppVerifier y otras herramientas similares. Vale la pena la inversión. En el libro, un capítulo entero está dedicado a las corrupciones de montón que (como ya se mencionó en la respuesta anterior) es muy probable que sea el problema al que se enfrenta.

Cuestiones relacionadas