“koşullu atlama veya hareket başlatılmamış değerlere bağlıdır” onaylama mesajı


166

Bu yüzden valgrind'den bazı gizemli başlatılmamış değerler mesajı alıyorum ve kötü değerin nereden kaynaklandığı oldukça gizemli.

Görünüşe göre valgrind, birleştirilmiş değerin kullanıldığı yeri gösterir, ancak başlatılmamış değerin kaynağını göstermez.

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

Görüldüğü gibi, oldukça şifreli olur .. özellikle çünkü Class :: MethodX derken, bazen doğrudan ostream vb işaret ediyor. Belki de bu optimizasyon nedeniyle mi?

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

Aynen böyle. Kaçırdığım bir şey var mı? Süper uzun printf dedektif çalışmalarına başvurmadan kötü değerleri yakalamanın en iyi yolu nedir?

Güncelleme:

Neyin yanlış olduğunu öğrendim, ama garip olan şey, valgrind kötü değer ilk kullanıldığında bunu bildirmedi. Bir çarpma fonksiyonunda kullanıldı:

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

Speedfac'ın birimlendirilmiş bir şamandıra olduğu yer. Ancak, o zaman rapor değil ve değeri yazdırılana kadar hatayı alıyorum değil .. Bu davranışı değiştirmek için valgrind için bir ayar var mı?

Yanıtlar:


230

--track-origins=yesBaşlatılmamış değerlerin kaynağını izlemesi için valgrind seçeneğini kullanın . Bu onu yavaşlatır ve daha fazla bellek alır, ancak başlatılmamış bir değerin kaynağını izlemeniz gerekiyorsa çok yardımcı olabilir.

Güncelleme: Başlatılmamış değerin rapor edildiği nokta ile ilgili olarak , valgrind el kitabı şunları belirtir :

Programınızın önemsiz (başlatılmamış) verileri istediğiniz kadar kopyalayabildiğini anlamak önemlidir. Memcheck bunu gözlemler ve verileri izler, ancak şikayet etmez. Şikayet, yalnızca programınız başlatılmamış verileri programınızın harici olarak görünür davranışını etkileyebilecek şekilde kullanmaya çalıştığında verilir.

Gönderen Valgrind SSS :

Başlatılmamış bellek değerlerinin kopyalarının istekli olarak rapor edilmesine gelince, bu, birçok kez önerilmiştir. Ne yazık ki, neredeyse tüm programlar, başlatılmamış bellek değerlerini yasal olarak kopyalar (çünkü derleyiciler hizalamayı korumak için yapıları doldurur) ve istekli kontrol yüzlerce yanlış pozitifliğe yol açar. Bu nedenle Memcheck şu anda istekli kontrolleri desteklememektedir.


1
Bu özelliği kullanmak için minimum geçerli sürüm nedir? 3.3.0 kullanıyorum ve seçenek gibi görünmüyor.
Robert S. Barnes

8
@Robert: --track-origins, valgrind 3.4.0'da eklendi
mark4o

20

Bunun anlamı, en azından kısmen başlatılmamış bir değeri yazdırmaya / çıktı vermeye çalışmanızdır. Tam olarak hangi değerin olduğunu bilmek için daraltabilir misiniz? Bundan sonra, kodun nerede başlatıldığını görmek için kodunuzu izleyin. Muhtemelen, tamamen başlatılmadığını göreceksiniz.

Daha fazla yardıma ihtiyacınız olursa, kaynak kodunun ilgili bölümlerini yayınlamak birisinin daha fazla rehberlik sunmasına izin verebilir.

DÜZENLE

Sorunu bulduğunu görüyorum. Valgrind'in birimleştirilmiş değişkenlere dayalı Koşullu atlama veya hareket izlediğini unutmayın . Bunun anlamı, programın yürütülmesi başlatılmamış değerden dolayı değiştirilirse (yani program örneğin bir if ifadesinde farklı bir dal alırsa) bir uyarı vermesidir. Gerçek aritmetik bir koşullu atlama veya hareket içermediğinden, valgrind sizi bu konuda uyarmadı. Bunun yerine, "başlatılmamış" durumunu kullanan ifadenin sonucuna yaydı.

Sizi hemen uyarmaması mantıksız görünebilir , ancak mark4o'nun belirttiği gibi bunu yapar, çünkü başlatılmamış değerler C'de her zaman kullanılır (örnekler: yapılarda dolgu, realloc()çağrı vb.) yanlış pozitif frekans nedeniyle çok faydalıdır.


Teşekkürler. Ben sadece neyin yanlış olduğunu öğrendim, ama garip şey, valgrind başka bir yerde kullanılana kadar unitialised değer şey rapor vermedi ..
kamziro

Bu kasıtlı. Başlatılmamış değerlerin kopyalanması veya aktarılması bir hata raporuna neden olsaydı, bunları yapılarda dolgudan her zaman alırsınız.
mark4o
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.