Então, eu recebi uma mensagem misteriosa de valores não inicializados da valgrind e tem sido um mistério até onde o valor ruim se originou.
Parece que valgrind mostra o local onde o valor unitializado acaba sendo usado, mas não a origem do valor não inicializado.
==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)
Como pode ser visto, fica bastante enigmático .. especialmente porque quando diz por Class :: MethodX, às vezes aponta direto para ostream etc. Talvez isso seja devido à otimização?
==11366== by 0x81109ED: Snake::SnakeBody::syncBodyPos() (ostream:221)
Bem desse jeito. Tem algo que estou perdendo? Qual é a melhor maneira de capturar valores ruins sem ter que recorrer a trabalhos de detetive de impressão muito longa?
Atualizar:
Eu descobri o que estava errado, mas o estranho é que a valgrind não informou quando o valor ruim foi usado pela primeira vez. Foi utilizado em uma função de multiplicação:
movespeed = stat.speedfactor * speedfac * currentbendfactor.val;
Onde speedfac era um flutuador unitizado. No entanto, naquele momento, não foi relatado e até que o valor seja impresso, eu recebo o erro. Existe uma configuração para o valgrind alterar esse comportamento?
O que isto significa é que você está tentando imprimir / gerar um valor que é pelo menos parcialmente não inicializado. Você pode reduzi-lo para saber exatamente qual é esse valor? Depois disso, rastreie seu código para ver onde ele está sendo inicializado. As chances são de que você verá que não está sendo totalmente inicializado.
Se você precisar de mais ajuda, publicar as seções relevantes do código-fonte pode permitir que alguém ofereça mais orientações.
EDITAR
Vejo que você encontrou o problema. Observe que o valgrind observa salto ou movimento condicional com base em variáveis unitializadas. O que isso significa é que ele só emitirá um aviso se a execução do programa for alterada devido ao valor não inicializado (ou seja, o programa assume uma ramificação diferente em uma instrução if, por exemplo). Como a aritmética real não envolveu um salto ou movimento condicional, a valgrind não o alertou sobre isso. Em vez disso, propagou o status "não inicializado" para o resultado da instrução que o usou.
Pode parecer contra-intuitivo que não o avise imediatamente, mas, como mark4o apontou, faz isso porque valores não inicializados são usados em C o tempo todo (exemplos: preenchimento de estruturas,
realloc()
chamada, etc.), para que esses avisos não sejam muito útil devido à frequência de falsos positivos.fonte