pinpointing " warunkowy skok lub ruch zależy od niezainicjowanej wartości(s)" komunikat valgrind

Więc otrzymałem jakąś tajemniczą niezainicjalizowaną wiadomość wartości od valgrind i to było dość tajemnicą, skąd pochodzi zła wartość.

Wydaje się, że valgrind pokazuje miejsce, w którym wartość unitialized kończy się używane, ale nie pochodzenie wartości unitialized.

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

Jak widać, robi się to dość tajemnicze.. zwłaszcza, że gdy mówi się przez Class:: MethodX, to czasami wskazuje prosto na ostream itp. Być może wynika to z optymalizacja?

==11366==    by 0x81109ED: Snake::SnakeBody::syncBodyPos() (ostream:221)
Tak po prostu. Coś mi umyka? Jaki jest najlepszy sposób na złapanie złych wartości bez konieczności uciekania się do bardzo długiej pracy detektywistycznej?

Aktualizacja:

Dowiedziałem się, co było nie tak, ale dziwne jest to, że valgrind nie zgłosił tego, gdy po raz pierwszy użyto złej wartości. Użyto go w funkcji mnożenia:

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

Gdzie speedfac był unifikowanym pływakiem. Jednak w tym czasie nie było to zgłaszane i nie dopóki wartość ma być wydrukowana, że otrzymam błąd.. Czy valgrind może zmienić to zachowanie?

 139
Author: kamziro, 2010-04-10

2 answers

Użyj opcji valgrind --track-origins=yes aby śledził pochodzenie niezainicjowanych wartości. Spowoduje to spowolnienie i zajmie więcej pamięci, ale może być bardzo pomocne, jeśli chcesz wyśledzić pochodzenie niezainicjowanej wartości.

Update: w odniesieniu do punktu, w którym podana jest niezainicjowana wartość, Instrukcja valgrind stwierdza :

Ważne jest, aby zrozumieć, że twój program może kopiować śmieci (niezainicjalizowane) dane tak samo, jak lubi. Memcheck obserwuje to i śledzi dane, ale nie skarży się. Reklamacja jest wystawiana tylko wtedy, gdy program próbuje wykorzystać niezainicjowane dane w sposób, który może wpłynąć na zewnętrzne zachowanie programu.

Z valgrind FAQ :

Jeśli chodzi o zgłaszanie kopii niezainicjowanych wartości pamięci, sugerowano to wielokrotnie. Niestety prawie wszystkie programy legalnie kopiują niezauważoną pamięć wartości wokół (ponieważ Kompilatory podkładają struktury, aby zachować wyrównanie) i chętne sprawdzanie prowadzi do setek fałszywych alarmów. W związku z tym Memcheck nie obsługuje w tej chwili chetnego sprawdzania.

 202
Author: mark4o,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-10 07:00:11

Oznacza to, że próbujesz wydrukować / wydrukować wartość, która jest przynajmniej częściowo niezaliczana. Możesz to zawęzić tak, że wiesz dokładnie, jaka to wartość? Następnie prześledzić kod, aby zobaczyć, gdzie jest inicjowany. Są szanse, zobaczysz, że nie jest w pełni zainicjowany.

Jeśli potrzebujesz więcej pomocy, opublikowanie odpowiednich sekcji kodu źródłowego może pozwolić komuś zaoferować więcej wskazówek.

EDIT

Widzę, że masz znalazłem problem. Zauważ, że valgrind obserwuje warunkowy skok lub ruch na podstawie unitializowanych zmiennych. Oznacza to, że wyda ostrzeżenie tylko wtedy, gdy wykonanie programu zostanie zmienione z powodu niezainicjalizowanej wartości(tj. na przykład program pobiera inną gałąź w instrukcji if). Ponieważ rzeczywista arytmetyka nie wymagała warunkowego skoku lub ruchu, valgrind nie ostrzegł cię o tym. Zamiast tego propagował status" niezaangażowanego " do wyniku oświadczenie, które go wykorzystało.

Może wydawać się sprzeczne z intuicją, że nie ostrzega cię od razu, ale jak zauważył mark4o, robi to, ponieważ niezainicjalizowane wartości są używane w C przez cały czas (przykłady: padding w strukturach, wywołanie realloc() itp.) ostrzeżenia te nie byłyby więc zbyt użyteczne ze względu na częstotliwość fałszywie dodatnią.

 17
Author: RarrRarrRarr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-10 06:55:29