identifiant «le saut ou le déplacement conditionnel dépend de la ou des valeurs non initialisées» message valgrind

166

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?

Kamziro
la source

Réponses:

230

Utilisez l'option valgrind --track-origins=yespour lui permettre de suivre l'origine des valeurs non initialisées. Cela ralentira et prendra plus de mémoire, mais peut être très utile si vous avez besoin de retrouver l'origine d'une valeur non initialisée.

Mise à jour: Concernant le point auquel la valeur non initialisée est signalée, le manuel valgrind déclare :

Il est important de comprendre que votre programme peut copier autant de données indésirables (non initialisées) qu'il le souhaite. Memcheck observe cela et garde une trace des données, mais ne se plaint pas. Une réclamation est émise uniquement lorsque votre programme tente d'utiliser des données non initialisées d'une manière qui pourrait affecter le comportement visible de l'extérieur de votre programme.

À partir de la FAQ Valgrind :

En ce qui concerne les rapports hâtifs de copies de valeurs de mémoire non initialisées, cela a été suggéré à plusieurs reprises. Malheureusement, presque tous les programmes copient légitimement des valeurs de mémoire non initialisées (car les compilateurs remplissent les structures pour préserver l'alignement) et une vérification avide conduit à des centaines de faux positifs. Par conséquent, Memcheck ne prend pas en charge la vérification hâtive pour le moment.

mark4o
la source
1
Quelle est la version minimale de valgrind pour utiliser cette fonctionnalité? J'utilise 3.3.0 et il ne semble pas aimer l'option.
Robert
8
@Robert: --track-origins a été ajouté dans valgrind 3.4.0
mark4o
20

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.

RarrRarrRarr
la source
Merci. Je viens de découvrir ce qui n'allait pas, mais la chose étrange est que valgrind n'a pas signalé la valeur unitaire jusqu'à ce qu'elle ait été utilisée ailleurs ..
kamziro
C'est intentionnel. Si le simple fait de copier ou de transmettre des valeurs non initialisées provoquait un rapport d'erreur, vous les obtiendriez tout le temps du remplissage des structures.
mark4o