2011-03-01 7 views
7

Me enfrenta a un problema que es tan misterioso, que ni siquiera sé cómo formular esta pregunta ... Ni siquiera puedo publicar ningún fragmento de código.Errores de tiempo de ejecución irreproducibles: ¿enfoque general?

Desarrollo un gran proyecto por mi cuenta, empecé desde cero. Ya casi es tiempo de liberación, pero no puedo deshacerme de algún error molesto. Mi programa escribe un archivo de salida de vez en cuando y durante ese recibo, ya sea:

  • error out_of_range std :: string
  • std :: string length_error
  • sólo un montón de tonterías sobre la producción

Vale la pena señalar que esos errores aparecen muy raramente y puede nunca reproducirse, incluso con la misma entrada. Memcheck no muestra ninguna violación de la memoria, incluso en las ejecuciones donde los errores se notaron previamente. Cppcheck tampoco tiene quejas. Uso STL y pthreads intensivamente, pero sin este último también ocurren errores.

Probé con los más recientes g ++ y icpc. Estoy ejecutando alguna versión de Ubuntu, pero no creo que esa sea la razón.

Les agradecería cualquier ayuda de ustedes, muchachos, sobre cómo abordar tales problemas. Gracias de antemano.

+0

A veces me encuentro con excepciones de cadenas, y la mayoría de las veces, esto se debe a que pasé los parámetros a los métodos de cadena al revés, por ejemplo , 'string :: append', para anexar un solo carácter, por ejemplo, el orden es count y luego char, a menudo lo he escrito al revés. Esto es realmente difícil de depurar hasta que ocurra algo raro ... – Nim

+0

¿Probablemente esto pertenece a los programadores no al stackoverflow? – CashCow

+0

¿Qué tan raro es "muy raramente"? Si lo ejecuta durante dos o tres horas, ¿cree que surgirá el error? –

Respuesta

2

Habilita los núcleos (ulimit -c o setrlimit()), obtén un núcleo y comienza a gdb'ing. O, si puede, realice una configuración en la que siempre se ejecute en gdb, de modo que cuando eventualmente ocurra el error, tenga algo de información disponible.

+0

+1. si puedo agregar: capture cualquier excepción (distinta de las que espera) en main y genere un volcado de núcleo usted mismo (vea http://stackoverflow.com/questions/979141/how-to-programatically-cause-a-core-dump -in-cc) – davka

+0

@davka: una vez que estás en main, has perdido la mayor parte de la pila ... –

+0

@ Matthieu: correcto, mi error. Es interesante, cuando no capto la excepción y el núcleo se abandona debido a una "excepción no controlada", la traza inversa muestra la pila. Así que tal vez debería cambiar la recomendación a ** "no capte ninguna excepción sino solo las que espera" **, es decir, comentar el 'catch (...)' si lo tiene – davka

1

y valgrind son herramientas muy útiles para la eliminación de errores como este. valgrind es especialmente potente para identificar problemas de acceso a la memoria y pérdidas de memoria.

+0

Creo que ya ha usado Memcheck y cppcheck. – DumbCoder

1

Encontré extraños errores de optimización en gcc (como un ++i que se ensambla en i++ en raras circunstancias). Podría tratar de declarar algunas variables críticas volatile, pero si valgrind no encuentra nada, las posibilidades son bajas. Y por supuesto es como disparar en la oscuridad ...

Si al menos puede detectar que algo está mal en una determinada ejecución desde el interior del programa, como la detección de salida sin sentido, entonces podría llamar a un "gotNonsense() vacío" "función que puede break en con gdb.

+1

Sí, a veces la optimización de gcc se comportaría de la manera más extraña e irracional posible. Puede intentar deshabilitar la optimización (-O0) y ver si el problema persiste. – Septagram

1

Si no puede determinar dónde se bloquea exactamente el programa en el código, una forma de encontrar ese lugar sería utilizar una salida de depuración. La salida de depuración es una buena manera de eliminar errores que no se pueden reproducir, ya que obtendrá más información sobre el error la próxima vez, sin la necesidad de reproducirlo activamente. Recomiendo usar algo de log lib para eso, boost proporciona uno, por ejemplo.

+2

+1, el registro extensivo ayudará a identificar el punto de falla. Puede ralentizar el programa, pero lo veo como un mal necesario cuando estás atrapado. –

+0

Si lo hace bien, puede deshabilitar el inicio de sesión en sus compilaciones de lanzamiento y mantenerlo solo para la depuración. Por ejemplo, si define QT_NO_DEBUG_OUTPUT para su aplicación Qt, todos los registros hechos con qDebug() serán recortados. Por lo tanto, no hay sanciones de rendimiento para los usuarios finales. Por supuesto, tenga en cuenta que la salida de depuración innecesaria desordena el código, así como los registros (cuando ya está buscando algo más), por lo que todavía necesita limpiar de vez en cuando. – Septagram

2

Los síntomas indican una corrupción de memoria.

Si tuviera que adivinar, diría que algo está dañando el estado interno del objeto std::string que estás escribiendo. ¿El objeto de cadena vive en la pila? ¿Ha eliminado el aplastamiento de pila como una posible causa (que no sería detectable por valgrind)?

También le sugiero que ejecute su ejecutable bajo un depurador, configurado de tal manera que desencadenaría un punto de interrupción cada vez que ocurra el problema. Esto le permitiría examinar el estado de su proceso en ese momento, lo que podría ser útil para descubrir qué está sucediendo.

1

Está utilizando STL intensivamente, por lo que puede intentar ejecutar su programa con libstdC++ en debug mode. Hará comprobaciones adicionales en iteradores, contenedores y algoritmos. Para usar el modo de depuración libstdC++, compile su aplicación con el indicador del compilador -D_GLIBCXX_DEBUG

Cuestiones relacionadas