точное указание «условный переход или перемещение зависит от неинициализированных значений» сообщение valgrind - PullRequest
154 голосов
/ 10 апреля 2010

Итак, я получил какое-то загадочное сообщение с неинициализированными значениями от 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?

Обновление:

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

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

Где спидфак был унитарным поплавком. Однако в то время об этом не сообщалось, и только после того, как значение должно быть напечатано, я получаю сообщение об ошибке. Существует ли параметр для valgrind, чтобы изменить это поведение?

Ответы [ 2 ]

220 голосов
/ 10 апреля 2010

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

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

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

Из FAQ по Valgrind :

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

20 голосов
/ 10 апреля 2010

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

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

EDIT

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

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

...