Должен ли я беспокоиться об условном переходе или перемещении, зависящем от неинициализированных значений?

Если вы использовали Memcheck (от Valgrind), вы, вероятно, знакомы с этим сообщением...

Условный переход или перемещение зависит от неинициализированных значений.

Я читал об этом, и это просто происходит, когда вы используете неинициализированное значение.

MyClass s;
s.DoStuff();

Это будет работать, потому что s инициализируется автоматически... Итак, если это так и это работает, почему Memcheck сообщает мне, что он не инициализирован? Следует ли игнорировать сообщение?

Возможно, я неправильно понял, куда меня вела ошибка. Из руководства Valgrind фактический ошибочный фрагмент...

int main()
{
  int x;
  printf ("x = %d\n", x);
}

Однако в моем коде я не вижу ничего подобного. Однако я заметил, что функция в верхней части трассировки стека, которую Memcheck показывает мне, является виртуальной функцией; может это как-то связано?

==14446== Conditional jump or move depends on uninitialised value(s)
==14446==    at 0x414164: vimrid::glut::GlutApplication::FinishRender() (GlutApplication.cpp:120)
==14446==    by 0x422434: vimrid::demos::filterdemos::FilterDemo3::Render() (FilterDemo3.cpp:260)
==14446==    by 0x412D3D: vimrid::VimridApplication::UpdateAndRender() (VimridApplication.cpp:93)
==14446==    by 0x4144BA: vimrid::glut::GlutApplication::glutHandleDisplay() (GlutApplication.cpp:201)
==14446==    by 0x41486A: vimrid::glut::GlutApplication::glutCallbackDisplay() (GlutApplication.cpp:277)
==14446==    by 0x54D9FAA: (within /usr/lib64/libglut.so.3.8.0)
==14446==    by 0x54DDA4A: fgEnumWindows (in /usr/lib64/libglut.so.3.8.0)
==14446==    by 0x54DA4A3: glutMainLoopEvent (in /usr/lib64/libglut.so.3.8.0)
==14446==    by 0x54DAEB5: glutMainLoop (in /usr/lib64/libglut.so.3.8.0)
==14446==    by 0x413FF8: vimrid::glut::GlutApplication::Run() (GlutApplication.cpp:112)
==14446==    by 0x41249D: vimrid::Launcher::runDemo(vimrid::VimridSettings&) (Launcher.cpp:150)
==14446==    by 0x412767: vimrid::Launcher::Launch(int, char**) (Launcher.cpp:62)

Обновление 1:

Я взглянул на GlutApplication.cpp:120, и похоже, что неинициализированная переменная передавалась функции в этой строке. Простой!


person Nick Bolton    schedule 19.04.2009    source источник
comment
Есть ли в MyClass конструктор?   -  person bk1e    schedule 19.04.2009
comment
Хм, я думаю, что я слишком много предполагал здесь, я перечеркнул это, так как я не думаю, что это вызывает проблему... Это функция FinishRender (я думаю)...   -  person Nick Bolton    schedule 19.04.2009


Ответы (6)


Можете ли вы опубликовать более полный образец? Трудно понять, как могла бы возникнуть эта конкретная ошибка без какой-либо формы оператора goto или изменения потока.

Я чаще всего вижу эту ошибку в коде, подобном следующему

MyClass s1;
...
if ( someCondition ) { 
  goto Foo:
}
MyClass s2;
Foo:
cout << s2.GetName();

Этот код в корне неверен. Причина в том, что хотя у s2 есть конструктор, он не выполняется, если someCondition истинно. Оператор goto перепрыгнет через инициализацию и в последней строке программы s2 будет неинициализирован и, по сути, укажет на мусор.

ИЗМЕНИТЬ

Вы также можете проверить эту страницу, которая дает подсказки о том, как расшифровать эту конкретную ошибку valgrind.

https://computing.llnl.gov/code/memcheck/#deciphering4

Дополнение

Еще одна распространенная причина этого, которую я только что обнаружил, заключается в том, что вы передаете некоторые целочисленные константы функции с переменным числом переменных, которые помещаются в стек как целые числа, но когда вызываемый объект получает их как longs, у вас возникает проблема на 64- битовые машины.

Я почти собирался сдаться и просто считать valgrind глупым, но потом понял, что простое приведение к длинному исправляет это.

Итак, мой вывод: отнеситесь к этим сообщениям серьезно.

person JaredPar    schedule 19.04.2009
comment
Согласитесь, это неправильно, поскольку это нелегально C++. Компилятор должен выкинуть это до того, как valgrind доберется до него. - person ; 19.04.2009
comment
...предполагая, конечно, что MyClass имеет определяемый пользователем конструктор. - person ; 19.04.2009
comment
Это может быть допустимым С++ - если MyClass является типом POD, то это допустимый С++ (даже если это плохая форма). - person Michael Burr; 19.04.2009
comment
@michael - да, вы правы, проблема в POD, а не в том, что я сказал о конструкторе. - person ; 19.04.2009

Вы можете добавить флаг --track-origins=yes в valgrind, и он даст вам информацию об источниках неинициализированных данных. Он работает медленнее, но может быть полезен.

Источник: Руководство пользователя Valgrind

person rocarvaj    schedule 15.04.2011

Если Valgrind заявляет, что значение не инициализировано, то в 99,5% случаев оно действительно не инициализировано. Обычно, когда компилятор сообщает об использовании неинициализированного значения (-Wuninitialized в GCC), вы проверяете встроенные развертывания, поскольку ваше неинициализированное значение может быть объявлено (а не инициализировано), например, 10 уровней встроенных функций «вызовы» (или развертывание шаблона) выше, чем фактический отчет GCC. Valgrind делает то же самое, но во время выполнения. Таким образом, вы должны проверить весь путь, по которому неинициализированное значение перемещалось от места объявления (и не инициализации) до места, где оно фактически используется. Путь может быть, например: каскад вызовов функций, где каждая функция передает свои аргументы (и, возможно, неинициализированное значение) следующей функции. Valgrind сообщит в последней функции, когда значение будет фактически использовано.

Как правило, вы не должны игнорировать то, что говорит Valgrind. Valgrind — это не простая программа трассировки. Его можно увидеть как виртуальную машину:

Valgrind — это, по сути, виртуальная машина, использующая методы JIT-компиляции, включая динамическую перекомпиляцию. Ничто из исходной программы никогда не запускается непосредственно на хост-процессоре. Вместо этого Valgrind сначала переводит программу во временную, более простую форму, называемую промежуточным представлением (IR), которая является независимой от процессора формой на основе SSA. После преобразования инструмент (см. ниже) может выполнять любые преобразования в IR, прежде чем Valgrind преобразует IR обратно в машинный код и позволит хост-процессору запустить его. Несмотря на то, что он может использовать динамическую трансляцию (т. е. хост-процессор и целевой процессор относятся к разным архитектурам), он этого не делает. Valgrind перекомпилирует двоичный код для запуска на хосте и целевых (или смоделированных) процессорах той же архитектуры. (Википедия)

person Community    schedule 19.04.2009

Было бы очень полезно, если бы вы могли опубликовать больше кода, особенно из той части, где, по мнению valgrind, возникла ошибка.

Если это происходит каждый раз, когда вы создаете экземпляр класса, возможно, вы забыли инициализировать один из членов конструктора.

И да: вы должны беспокоиться об этой ошибке, эти ребята действительно могут вас укусить.

person bayer    schedule 19.04.2009

На 64-битной машине. Обычно int занимает в памяти 4 байта. Но long займет в памяти 8 байт. Поэтому просто укажите значение int, так как длинный формат приведет к совершенно неправильному результату. В этой ситуации нужен конвертер.

person wuxianyun    schedule 30.04.2012

Ошибка, похоже, не связана с вашим кодом, а с библиотекой, которую вы используете.

Valgrind поставляется с некоторым подавлением ошибок по умолчанию, но это, вероятно, не распространяется на библиотеку, которую вы используете.

Инструменты проверки ошибок обнаруживают многочисленные проблемы в базовых библиотеках, таких как библиотека GNU C и клиентские библиотеки X11, которые предустановлены в вашей системе GNU/Linux. Вы не можете легко исправить это, но вы не хотите видеть эти ошибки (и да, их много!). Поэтому Valgrind считывает список ошибок, которые нужно подавить при запуске. Файл подавления по умолчанию создается сценарием ./configure при сборке системы.

Вы можете создавать свои собственные подавления ошибок, которые вам известны. не имеют отношения к вашему коду.

См. аналогичный вопрос SO Почему Valgrind не нравится мое использование glutCreateWindow ?

person lothar    schedule 20.04.2009