Могу ли я заставить valgrind сказать мне, какое значение не инициализировано? - PullRequest
0 голосов
/ 19 сентября 2018

Я запустил valgrind для некоторого кода следующим образом:

valgrind --tool=memcheck --leak-check=full --track-origins=yes ./test

Возвращает следующую ошибку:

==24860== Conditional jump or move depends on uninitialised value(s)
==24860==    at 0x4081AF: GG::fl(M const&, M const&) const (po.cpp:71)
==24860==    by 0x405CDB: MO::fle(M const&, M const&) const (m.cpp:708)
==24860==    by 0x404310: M::operator>=(M const&) const (m.cpp:384)
==24860==    by 0x404336: M::operator<(M const&) const (m.cpp:386)
==24860==    by 0x4021FD: main (test.cpp:62)
==24860==  Uninitialised value was created by a heap allocation
==24860==    at 0x4C2EBAB: malloc (vg_replace_malloc.c:299)
==24860==    by 0x40653F: GODA<unsigned int>::allocate_new_block() (goda.hpp:82)
==24860==    by 0x406182: GODA<unsigned int>::GODA(unsigned long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool) (goda.hpp:103)
==24860==    by 0x402A0E: M::init(unsigned long) (m.cpp:63)
==24860==    by 0x403831: M::M(std::initializer_list<unsigned int>, MO const*) (m.cpp:248)
==24860==    by 0x401B56: main (test.cpp:31)

Таким образом, строка 71 содержит ошибку.Ок, отлично.Вот строки, ведущие к строке 71 из po.cpp (строка 71 является последней):

DEG_TYPE dtk = t.ord_deg();
DEG_TYPE duk = u.ord_deg();
bool searching = dtk == duk;
NVAR_TYPE n = t.nv();
NVAR_TYPE k = 0;
for (/* */; searching and k < n; ++k) { // this is line 71

OK, поэтому какое значение строки 71 не инициализировано?

  • определенно нет k;
  • Я вручную проверил (= "пошаговое выполнение gdb"), что конструктор t инициализирует значение, возвращаемое t.nv(), поэтому, безусловно,не n (на самом деле n установлено на 6, правильное значение);
  • searching определяется dtk и duk, но я также вручную проверил, что t 'Конструкторы s и u инициализируют значения, возвращаемые .ord_deg() (на самом деле для dtk и duk установлено значение 3, правильное значение).

I 'м в полной растерянности здесь.Есть ли какая-нибудь опция, которая сообщит valgrind сообщить , какое точное значение оно считает неинициализированным?

Обновление

В ответ на один вопросВот строка 61 из test.cpp:

M s { 1, 0, 5, 2, 0 };

. Таким образом, она создается с использованием списка инициализаторов.Вот этот конструктор:

M::M(
    initializer_list<EXP_TYPE> p, const MO * ord
) {
  common_init(ord);
  init_e(p.size());
  NVAR_TYPE i = 0;
  last = 0;
  for (
       auto pi = p.begin();
       pi != p.end();
       ++pi
  ) {
    if (*pi != 0) {
      e[last] = i;
      e[last + 1] = *pi;
      last += 2;
    }
    ++i;
  }
  ord->set_data(*this);
}

Вот данные в классе с добавлением комментариев, показывающих, где они инициализированы:

NVAR_TYPE n;    // init_e()
EXP_TYPE * e;   // common_init()
NVAR_TYPE last; // common_init()
DEG_TYPE od;    // common_init(), revised in ord->set_data()
const MO * o;   // common_init()
MOD * o_data;   // common_init(), revised in ord->set_data()

Ответы [ 6 ]

0 голосов
/ 22 сентября 2018

Есть ли какая-либо опция, которая скажет valgrind сообщить, какое точное значение, по его мнению, неинициализировано?

Лучшее, что вы можете сделать, это использовать --track-origins=yes (вы уже используете эту опцию).Valgrind сообщит вам только приблизительное местоположение неинициализированных значений (происхождение в терминах Valgrind), но не точное имя переменной.См. Руководство Valgrind для --track-origins:

Если установлено значение yes, Memcheck отслеживает происхождение всех неинициализированных значений.Затем, когда сообщается об ошибке неинициализированного значения, Memcheck попытается показать происхождение значения.Источник может быть одним из следующих четырех мест: блок кучи, распределение стека, запрос клиента или другие источники (например, вызов brk).

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

0 голосов
/ 22 сентября 2018

Вы можете использовать gdb + vgdb + valgrind для отладки вашей программы под valgrind.

Затем, когда valgrind останавливается на сообщенной выше ошибке, вы можете проверить определенность переменных, которые вас интересуют, используя монитор.запросите 'xb' или 'get_vbits', задав адрес переменной, а затем проверив vbits для определения размера переменной.

Например:

p &searching
=> 0xabcdef
monitor xb 0xabcdef 1
=> will show you the value of searching and the related vbits.

Для получения более подробной информации,см. «Отладка вашей программы с использованием Valgrind gdbserver и GDB» http://www.valgrind.org/docs/manual/manual-core-adv.html#manual-core-adv.gdbserver и «Команды Memcheck Monitor» http://www.valgrind.org/docs/manual/mc-manual.html#mc-manual.monitor-commands

0 голосов
/ 20 сентября 2018

Вы просматриваете неправильную трассировку стека.

Valgrind сообщает вам, что неинициализированное значение было создано выделением кучи:

==24860==  Uninitialised value was created by a heap allocation
==24860==    at 0x4C2EBAB: malloc (vg_replace_malloc.c:299)
==24860==    by 0x40653F: GODA<unsigned int>::allocate_new_block() (goda.hpp:82)
==24860==    by 0x406182: GODA<unsigned int>::GODA(unsigned long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool) (goda.hpp:103)
==24860==    by 0x402A0E: M::init(unsigned long) (m.cpp:63)
==24860==    by 0x403831: M::M(std::initializer_list<unsigned int>, MO const*) (m.cpp:248)
==24860==    by 0x401B56: main (test.cpp:31)

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

==24860==    by 0x402A0E: M::init(unsigned long) (m.cpp:63)

Скорее всего, неинициализированная переменная должна быть в m.cpp:63 строке кода.

0 голосов
/ 19 сентября 2018

Вы должны понимать, как работает memcheck.Чтобы избежать появления чрезмерных ошибок, неинициализированные значения не помечаются, пока они не окажут возможного влияния на ваш код.Неинициализированная информация распространяется по присваиваниям.

// if ord_deg returns something that is uninitialized, dtk and/or duk will be
// flagged internally as uninitialized but no error issued
DEG_TYPE dtk = t.ord_deg();
DEG_TYPE duk = u.ord_deg();
// again transitively if either dtk or duk is flagged as uninitialized then
// searching will be flagged as uninitialized, and again no error issued
bool searching = dtk == duk;
// if nv() returns something that is uninitialized, n will be
// flagged internally as unintialized
NVAR_TYPE n = t.nv();
// k is flagged as initialized
NVAR_TYPE k = 0;
// OK now the values of searching and n affect your code flow
// if either is uninitialized then memcheck will issue an error
for (/* */; searching and k < n; ++k) { // this is line 71
0 голосов
/ 19 сентября 2018

Вы можете использовать clang-tidy в качестве альтернативы для поиска неинициализированных переменных.QtCreator 4.7 имеет полную интеграцию clang-tidy, выберите «Clang-Tidy and Clazy» на панели отладки, нажмите run, выберите файлы, которые вы хотите протестировать.

0 голосов
/ 19 сентября 2018

Из документации Valgrind ,

4.2.2.Использование неинициализированных значений
...

Источники неинициализированных данных обычно бывают:
- Локальные переменные в процедурах, которые не были инициализированы, как в примере выше.
- Содержимое блоков кучи (выделенных с помощью malloc, new или аналогичной функции) перед тем, как вы (или конструктор) что-то там напишете.

У вас есть:

==24860==  Uninitialised value was created by a heap allocation
==24860==    at 0x4C2EBAB: malloc (vg_replace_malloc.c:299)
==24860==    by 0x40653F: GODA<unsigned int>::allocate_new_block() (goda.hpp:82)

Поэтому весьма вероятно, что malloc, используемый GODA<unsigned int>::allocate_new_block(), вызывает эту ошибку.

...