Donc, j'ai reçu un mystérieux message de valeurs non initialisées de valgrind et cela a été assez mystérieux quant à l'origine de la mauvaise valeur.
Il semble que valgrind montre l'endroit où la valeur unitaire finit par être utilisée, mais pas l'origine de la valeur non initialisée.
==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)
Comme on peut le voir, cela devient assez cryptique .. surtout parce que quand il dit par Class :: MethodX, il pointe parfois directement vers ostream etc. Peut-être est-ce dû à l'optimisation?
==11366== by 0x81109ED: Snake::SnakeBody::syncBodyPos() (ostream:221)
Juste comme ça. Y a-t-il quelque chose qui me manque? Quelle est la meilleure façon d'attraper de mauvaises valeurs sans avoir à recourir à un travail de détective très long?
Mettre à jour:
J'ai découvert ce qui n'allait pas, mais la chose étrange est que valgrind ne l'a pas signalé lorsque la mauvaise valeur a été utilisée pour la première fois. Il a été utilisé dans une fonction de multiplication:
movespeed = stat.speedfactor * speedfac * currentbendfactor.val;
Où speedfac était un flotteur unifié. Cependant, à ce moment-là, il n'a pas été signalé et ce n'est que lorsque la valeur doit être imprimée que j'obtiens l'erreur .. Y at-il un paramètre pour valgrind pour modifier ce comportement?
Cela signifie que vous essayez d'imprimer / de sortir une valeur qui est au moins partiellement non initialisée. Pouvez-vous le réduire afin de savoir exactement quelle valeur cela représente? Après cela, parcourez votre code pour voir où il est initialisé. Il y a de fortes chances que vous constatiez qu'il n'est pas complètement initialisé.
Si vous avez besoin de plus d'aide, la publication des sections pertinentes du code source peut permettre à quelqu'un d'offrir plus de conseils.
ÉDITER
Je vois que vous avez trouvé le problème. Notez que valgrind surveille les sauts conditionnels ou les déplacements basés sur des variables unifiées. Cela signifie qu'il ne donnera un avertissement que si l'exécution du programme est modifiée en raison de la valeur non initialisée (c'est-à-dire que le programme prend une branche différente dans une instruction if, par exemple). Puisque l'arithmétique réelle n'impliquait pas de saut ou de mouvement conditionnel, valgrind ne vous en a pas averti. Au lieu de cela, il a propagé l'état "non initialisé" au résultat de l'instruction qui l'utilisait.
Cela peut sembler contre-intuitif qu'il ne vous prévienne pas immédiatement, mais comme mark4o l'a souligné, il le fait parce que des valeurs non initialisées sont utilisées en C tout le temps (exemples: remplissage dans les structures, l'
realloc()
appel, etc.) donc ces avertissements ne seraient pas très utile en raison de la fréquence des faux positifs.la source