Pinpointing "условный переход или перемещение зависит от неинициализированного значения (значений)" valgrind message

Итак, у меня появилось какое-то таинственное неинициализированное значение сообщения от valgrind, и это была таинственность, из-за которой возникла плохая стоимость.

Кажется, что valgrind показывает место, где используется унифицированное значение, но не начало неинициализированного значения.

==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)

Как видно, он становится довольно загадочным.. особенно потому, что когда он говорит Class:: MethodX, он иногда указывает прямо на ostream и т.д. Возможно, это связано с оптимизацией?

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

Просто так. Есть что-то, что мне не хватает? Каков наилучший способ поймать плохие ценности, не прибегая к сверхдолгому детективу printf?

Update:

Я узнал, что было не так, но, как ни странно, valgrind не сообщал об этом, когда сначала использовалась плохая стоимость. Он использовался в функции умножения:

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

Где speedfac был унифицированным поплавком. Тем не менее, в то время он не сообщался и не до тех пор, пока значение не будет напечатано, чтобы получить ошибку. Есть ли параметр valgrind, чтобы изменить это поведение?

Ответ 1

Используйте параметр valgrind --track-origins=yes, чтобы отслеживать происхождение неинициализированных значений. Это сделает его медленнее и займет больше памяти, но может быть очень полезно, если вам нужно отслеживать происхождение неинициализированного значения.

Обновление: Что касается точки, в которой сообщается неинициализированное значение, указано в инструкциях valgrind:

Важно понимать, что ваша программа может копировать вокруг нежелательных (неинициализированных) данных столько, сколько ей нравится. Memcheck наблюдает это и отслеживает данные, но не жалуется. Жалоба выдается только тогда, когда ваша программа пытается использовать неинициализированные данные таким образом, что может повлиять на поведение вашей программы внешне.

Из Valgrind FAQ:

Что касается нетерпеливой отчетности о копиях неинициализированных значений памяти, это было предложено несколько раз. К сожалению, почти все программы на законных основаниях копируют неинициализированные значения памяти вокруг (потому что структуры компиляторов для сохранения выравнивания) и нетерпеливая проверка приводят к сотням ложных срабатываний. Поэтому Memcheck в настоящее время не поддерживает нетерпеливую проверку.

Ответ 2

Это означает, что вы пытаетесь распечатать/вывести значение, которое хотя бы частично неинициализировано. Можете ли вы сузить его, чтобы вы точно знали, что это такое? После этого проведите свой код, чтобы узнать, где он инициализируется. Скорее всего, вы увидите, что он не полностью инициализирован.

Если вам нужна дополнительная помощь, размещение соответствующих разделов исходного кода может позволить кому-то предложить дополнительные рекомендации.

ИЗМЕНИТЬ

Я вижу, что вы нашли проблему. Обратите внимание, что valgrind наблюдает за условным прыжком или движением на основе унифицированных переменных. Это означает, что он выдаст предупреждение только в том случае, если выполнение программы будет изменено из-за неинициализированного значения (т.е. Программа, например, использует другую ветвь в выражении if). Поскольку фактическая арифметика не включала условный переход или движение, valgrind не предупреждал вас об этом. Вместо этого он распространил "неинициализированный" статус на результат оператора, который использовал его.

Может показаться нелогичным то, что он не сразу предупреждает вас, но как указано mark4o, это делает это, потому что неинициализированные значения все время используются в C (примеры: заполнение в структурах, realloc() call и т.д.), поэтому эти предупреждения не будут очень полезны из-за ложной положительной частоты.