c++ - lost - La localización exacta de "salto condicional o movimiento depende de valores sin inicializar" valgrind message
valgrind ubuntu (2)
Así que he estado recibiendo un misterioso mensaje de valores no inicializados de valgrind y ha sido todo un misterio el origen del mal valor.
Parece que valgrind muestra el lugar donde termina el uso del valor unificado, 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 dice Class :: MethodX, a veces apunta directamente a ostream, etc. ¿Quizás esto se deba a la optimización?
==11366== by 0x81109ED: Snake::SnakeBody::syncBodyPos() (ostream:221)
Así. ¿Se me escapa algo? ¿Cuál es la mejor manera de detectar los valores erróneos sin tener que recurrir al trabajo detectivesco super-largo?
Actualizar:
Descubrí lo que estaba mal, pero lo extraño es que Valgrind no lo informó cuando se utilizó por primera vez el valor malo. Fue utilizado en una función de multiplicación:
movespeed = stat.speedfactor * speedfac * currentbendfactor.val;
Donde speedfac era un flotador unitario. Sin embargo, en ese momento no se informó y no fue hasta que se imprimió el valor que recibí el error. ¿Hay alguna opción para que valgrind cambie este comportamiento?
Lo que esto significa es que está tratando de imprimir / generar un valor que al menos parcialmente no está inicializado. ¿Puedes limitarlo para que sepas exactamente qué valor tiene? Después de eso, trace a través de su código para ver dónde se está inicializando. Lo más probable es que veas que no se está inicializando por completo.
Si necesita más ayuda, publicar las secciones relevantes del código fuente podría permitirle a alguien ofrecer más orientación.
EDITAR
Veo que has encontrado el problema. Tenga en cuenta que valgrind busca salto condicional o movimiento basado en variables unitarias. Lo que eso significa es que solo emitirá 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 instrucción if, por ejemplo). Dado que la aritmética real no implicaba un salto o movimiento condicional, valgrind no te lo advirtió. En cambio, propagó el estado "no inicializado" al resultado de la declaración que lo utilizó.
Puede parecer contradictorio que no lo advierta de inmediato, pero como señaló mark4o , lo hace porque los valores no inicializados se usan en C todo el tiempo (ejemplos: relleno en estructuras, la llamada a realloc()
, etc.) entonces esas advertencias no sería muy útil debido a la frecuencia de falso positivo.
Utilice la opción --track-origins=yes
para hacer que --track-origins=yes
el origen de los valores no inicializados. Esto lo hará más lento y llevará más memoria, pero puede ser muy útil si necesita rastrear el origen de un valor no inicializado.
Actualización: Con respecto al punto en el que se informa el valor no inicializado, el manual de valgrind indica :
Es importante comprender que su programa puede copiar datos basura (no inicializados) tanto como quiera. Memcheck observa esto y realiza un seguimiento de los datos, pero no se queja. Una queja se emite solo cuando su programa intenta utilizar datos no inicializados de una manera que pueda afectar el comportamiento externo visible de su programa.
De las preguntas frecuentes de Valgrind :
En cuanto al informe ansioso de copias de valores de memoria no inicializados, esto ha sido sugerido varias veces. Desafortunadamente, casi todos los programas copian legítimamente los valores de memoria no inicializados (porque los compiladores rellenan las estructuras para preservar la alineación) y la comprobación ansiosa conduce a cientos de falsos positivos. Por lo tanto, Memcheck no es compatible con la comprobación ansiosa en este momento.