señalar " salto condicional o movimiento depende de valor(s) no iniciado (s)" valgrind message


Así que he estado recibiendo algunos mensajes de valores misteriosos no inicializados de valgrind y ha sido bastante misterioso a partir de dónde se originó el mal valor.

Parece que valgrind muestra el lugar donde termina siendo utilizado el valor unitializado, pero no el origen del valor no inicializado.

==11366== Conditional jump or move depends on uninitialised value(s)
==11366==    at 0x43CAE4F: __printf_fp (in /lib/tls/i686/cmov/libc-2.7.so)
==11366==    by 0x43C6563: vfprintf (in /lib/tls/i686/cmov/libc-2.7.so)
==11366==    by 0x43EAC03: vsnprintf (in /lib/tls/i686/cmov/libc-2.7.so)
==11366==    by 0x42D475B: (within /usr/lib/libstdc++.so.6.0.9)
==11366==    by 0x42E2C9B: std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert_float<double>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, char, double) const (in /usr/lib/libstdc++.so.6.0.9)
==11366==    by 0x42E31B4: std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::do_put(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, double) const (in /usr/lib/libstdc++.so.6.0.9)
==11366==    by 0x42EE56F: std::ostream& std::ostream::_M_insert<double>(double) (in /usr/lib/libstdc++.so.6.0.9)
==11366==    by 0x81109ED: Snake::SnakeBody::syncBodyPos() (ostream:221)
==11366==    by 0x810B9F1: Snake::Snake::update() (snake.cpp:257)
==11366==    by 0x81113C1: SnakeApp::updateState() (snakeapp.cpp:224)
==11366==    by 0x8120351: RoenGL::updateState() (roengl.cpp:1180)
==11366==    by 0x81E87D9: Roensachs::update() (rs.cpp:321)

Como se puede ver, se vuelve bastante críptico.. especialmente porque cuando se dice by Class:: methodX, a veces apunta directamente a ostream, etc. Tal vez esto se debe a optimización?

==11366==    by 0x81109ED: Snake::SnakeBody::syncBodyPos() (ostream:221)

Así como así. ¿Hay algo que me estoy perdiendo? ¿Cuál es la mejor manera de atrapar los malos valores sin tener que recurrir a un trabajo de detective de printf súper largo?

Actualizar:

Descubrí lo que estaba mal, pero lo extraño es que valgrind no lo reportó cuando se usó por primera vez el valor malo. Se utilizó en una función de multiplicación:

movespeed = stat.speedfactor * speedfac * currentbendfactor.val;

Donde speedfac era un flotador unitializado. However, at that time it was not reported y no hasta que el valor se va a imprimir que me sale el error.. ¿Hay una configuración para que valgrind cambie este comportamiento?

 139
Author: kamziro, 2010-04-10

2 answers

Utilice la opción valgrind --track-origins=yes para que rastree el origen de los valores no inicializados. Esto lo hará más lento y tomará más memoria, pero puede ser muy útil si necesita rastrear el origen de un valor no iniciado.

Actualización: Con respecto al punto en el que se informa el valor no inicializado, el manual de valgrind indica :

Es importante entender que su programa puede copiar alrededor de datos basura (no iniciados) tanto como como. Memcheck observa esto y realiza un seguimiento de los datos, pero no se queja. Una queja se emite solo cuando su programa intenta hacer uso de datos no iniciados de una manera que podría afectar el comportamiento visible externamente de su programa.

De la Valgrind FAQ :

En cuanto a los informes ansiosos de copias de valores de memoria no inicializados, esto se ha sugerido varias veces. Desafortunadamente, casi todos los programas copian legítimamente la memoria no iniciada los valores alrededor (porque los compiladores rellenan estructuras para preservar la alineación) y la comprobación ansiosa conduce a cientos de falsos positivos. Por lo tanto, Memcheck no admite eager checking en este momento.

 202
Author: mark4o,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-10 07:00:11

Lo que esto significa es que está tratando de imprimir/generar un valor que está al menos parcialmente no iniciado. ¿Puedes reducirlo para saber exactamente qué valor es? Después de eso, rastrea tu código para ver dónde se está inicializando. Lo más probable es que vea que no se está inicializando completamente.

Si necesita más ayuda, publicar las secciones relevantes del código fuente podría permitir que alguien le ofrezca más orientación.

EDITAR

Veo que has encontré el problema. Tenga en cuenta que valgrind observa Salto condicional o movimiento basado en variables unitializadas. Lo que eso significa es que solo dará una advertencia si la ejecución del programa se altera debido al valor no inicializado (es decir. el programa toma una rama diferente en una sentencia if, por ejemplo). Dado que la aritmética real no implicaba un salto o movimiento condicional, valgrind no le advirtió de eso. En su lugar, propagó el estado "no inicializado" al resultado de la declaración que lo usó.

Puede parecer contradictorio que no te advierta inmediatamente, pero como mark4o señaló, lo hace porque los valores no inicializados se usan en C todo el tiempo (ejemplos: relleno en estructuras, la llamada realloc(), etc.) así que esas advertencias no serían muy útiles debido a la frecuencia de falsos positivos.

 17
Author: RarrRarrRarr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-10 06:55:29