“조건부 점프 또는 이동은 초기화되지 않은 값에 따라 다릅니다.”
그래서 나는 valgrind로부터 신비한 초기화되지 않은 값 메시지를 받고 있으며 나쁜 값이 유래 한 곳은 꽤 신비했습니다.
valgrind는 단위 화 된 값이 사용되는 곳을 보여 주지만 초기화되지 않은 값의 출처는 아닙니다.
==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)
보시다시피, 그것은 상당히 비밀을 얻습니다. 특히 Class :: MethodX에 의해 말할 때 때로는 ostream 등을 가리 키기 때문입니다. 아마도 이것이 최적화 때문입니까?
==11366== by 0x81109ED: Snake::SnakeBody::syncBodyPos() (ostream:221)
그냥 그렇게 내가 놓친 것이 있습니까? 매우 긴 printf 형사 작업에 의존하지 않고 나쁜 가치를 포착하는 가장 좋은 방법은 무엇입니까?
최신 정보:
나는 무엇이 잘못되었는지 알았지 만, 이상한 점은, valgrind는 나쁜 가치가 처음 사용될 때 그것을보고하지 않았다는 것입니다. 곱셈 함수에서 사용되었습니다.
movespeed = stat.speedfactor * speedfac * currentbendfactor.val;
speedfac은 단일화 된 플로트였습니다. 그러나 그 당시에는 오류가 발생하여 값이 인쇄 될 때까지보고되지 않았습니다.이 동작을 변경하기 위해 valgrind에 대한 설정이 있습니까?
valgrind 옵션 --track-origins=yes
을 사용하여 초기화되지 않은 값의 원점을 추적하십시오. 이렇게하면 속도가 느려지고 더 많은 메모리가 필요하지만 초기화되지 않은 값의 출처를 추적해야하는 경우 매우 유용 할 수 있습니다.
업데이트 : 초기화되지 않은 값이보고되는 시점과 관련 하여 valgrind 수동 상태는 다음과 같습니다.
프로그램은 정크 데이터 (초기화되지 않은) 데이터를 원하는만큼 복사 할 수 있음을 이해하는 것이 중요합니다. Memcheck는이를 관찰하고 데이터를 추적하지만 불평하지는 않습니다. 불만은 프로그램이 외부에서 볼 수있는 행동에 영향을 줄 수있는 방식으로 초기화되지 않은 데이터를 사용하려고 할 때만 발행됩니다.
로부터 Valgrind의 자주 묻는 질문 :
초기화되지 않은 메모리 값의 복사본을 열망 적으로보고하는 경우 여러 번 제안되었습니다. 불행히도, 거의 모든 프로그램은 초기화되지 않은 메모리 값을 합법적으로 복사하고 (컴파일러는 정렬을 유지하기 위해 구조체를 패딩하기 때문에) 수백 가지 오탐을 유발합니다. 따라서 Memcheck는 현재 열성적인 검사를 지원하지 않습니다.
이것은 적어도 부분적으로 초기화되지 않은 값을 인쇄 / 출력하려고한다는 것을 의미합니다. 정확히 어떤 값인지 알 수 있도록 범위를 좁힐 수 있습니까? 그런 다음 코드를 추적하여 초기화되는 위치를 확인하십시오. 기회가 완전히 초기화되지 않았 음을 알 수 있습니다.
도움이 더 필요한 경우 소스 코드의 관련 섹션을 게시하면 더 많은 지침을 제공 할 수 있습니다.
편집하다
문제를 발견 한 것으로 보입니다. valgrind는 단일화 된 변수를 기준으로 조건부 점프 또는 이동을 감시 합니다. 즉, 초기화되지 않은 값으로 인해 프로그램 실행이 변경되는 경우에만 경고가 표시됩니다 (예 : 프로그램이 if 문에서 다른 분기를 수행함). 실제 산술에는 조건부 점프 나 이동이 포함되지 않았기 때문에 valgrind는 이에 대해 경고하지 않았습니다. 대신, "초기화되지 않은"상태를 사용한 명령문의 결과로 전파했습니다.
즉시 경고하지는 않지만 반 직관적 인 것처럼 보일 수 있지만, mark4o가 지적했듯이 초기화되지 않은 값은 C에서 항상 사용되므로 (예 : 구조의 패딩, realloc()
호출 등) 이러한 경고가 표시되지 않습니다. 위양성 빈도로 인해 매우 유용합니다.
'IT' 카테고리의 다른 글
JavaScript에서 JSON 문자열을 특정 객체 프로토 타입으로 구문 분석 (0) | 2020.06.05 |
---|---|
SQL WHERE .. IN 절 여러 열 (0) | 2020.06.05 |
ASP.NET MVC에서 비동기 작업을 수행하려면 .NET 4의 ThreadPool에서 스레드를 사용하십시오. (0) | 2020.06.05 |
TypeError : 필수 위치 인수 1 개가 없습니다 : 'self' (0) | 2020.06.05 |
자바 스크립트 파일을 동적으로로드 (0) | 2020.06.05 |