2016-06-16 2 views
2

힙에 객체 묶음이있는 평범하지 않은 소프트웨어 프로젝트를 디버깅하고 있습니다. 어떤 시점에서 (적어도) 이러한 객체 중 하나가 손상됩니다.힙에 손상된 객체 디버깅

내 클래스에 const 회원을 추가하여 카나리아 역할을하고 실제로는 실행 중에 손상됩니다. 일반적으로 메모리에 기록 할 시점을 알아 내기 위해이 변수에 감시 점을 추가합니다. 그러나 어떤 인스턴스가 덮어 쓰여지는지 알지 못합니다. 클래스에 저장된 정보도 손상됩니다.

각 개체에 감시 점을 설정할 개체가 너무 많아서 더 작은 입력 집합으로 재생할 수 없었습니다. valgrind를 실행하는 중 "4 크기의 유효하지 않은 읽기"가 표시되는데 이는 4 바이트의 카나리아 int를 읽었지만이 시점에서는 이미 너무 늦었습니다.

여기에서 진행하는 방법에 대한 제안 사항이 있으십니까?

+0

제목 (. 나는 초기화되지 않은 값이 -Wuninitialized와 컴파일러에 의해 검출 될 수 있지만, 분명히 그 소리의 내 버전 (사과) -Wall 활성화로 언급처럼 느끼지 않았다 알고있다). 질문 : "스택에". 너의 마음을 위로 해주세요. – molbdnilo

+0

손상이 발생하기 전에 일부 객체가 삭제 되었습니까? '크기 4의 유효하지 않은 읽기'는 해제 된 메모리 나 할당 된 메모리 블록 외부와 같이해서는 안되는 데이터를 읽음을 의미합니다. valgrind 님이 더 자세한 정보를 제공하지 않습니까? 전체 valgrind 추적을 게시 할 수 있습니까? – Tryum

+0

소스 코드를 검토하십시오. 그러한 부패가 발생할 수있는 원인은 무엇입니까? 프로그램이 멀티 스레드되고 적절한 동기화가 사용되지 않았습니까? 이러한 개체에 대한 포인터가 공유되고 소유자 중 하나가 다른 소유자에게 알리지 않고 메모리를 할당 해제했을 수 있습니까? 등등. – PaulMcKenzie

답변

1

문제점을 일으키는 원인을 찾아 낼 수있었습니다. 처음부터 결코 보지 못했던 물건을 발견합니다. @ employ-russian처럼, 나는 내가 알지 못하는 곳에 내 물건이 삭제되었을 수도 있는지 궁금해했다. 소멸자에 중단 점을 두는 것은 아무런 합리적인 설명이 없으므로 포인터 자체가 유효하지 않아서 클래스의 유효한 인스턴스가 아닌 메모리를 가리 킵니다.

Lo 및 보라; 역 참조였던 포인터는 다른 클래스의 일부 생성자에 의해 초기화되지 않은 상태로 남았습니다. null에 대한 명시적인 확인을 추가하면 Valgrind의 오류는 Conditional jump or move depends on uninitialised value(s)이되었습니다. --track-origins=yes을 사용하여 초기화되지 않은 데이터의 소스, 즉 초기화 목록에서 누락 된 포인터를 신속하게 파악했습니다. "힙에"

1

아마도 이것만으로는 충분하지 않지만, 비슷한 문제가있을 때 여기에 내가 한 일이 있습니다. 결정적인 방식으로 문제를 재현 할 수 있다고 가정합니다.

내 전략은 문제를 가장 먼저 유발 한 인스턴스를 찾는 것이 었습니다. 이 증상을 드러내는 특정 라인의 카운터를 사용했습니다. 예를 들어, Visual Studio에서 100000 번째 히트를 트리거하는 중단 점을 설정하면 결코 중단되지 않습니다. 그러나 Visual Studio는 실행 중 중단 점이 몇 번이나 발생했는지 알려줍니다. 시행 착오를 통해 문제가 breakpoint가 발생하는 20 번에 발생한다는 것을 알았습니다. 따라서 손상이 발생하기 전에 적절한 인스턴스를 구별 할 수 있도록 브레이크 포인트를 19 번째 반복에서 트리거하도록 설정했습니다.

거기에서 시작하여 이전에 손상된 변수의 주소를 가지고 디버거와 함께 무슨 일이 일어나고 있는지 알아볼 수 있습니다 : 오류가있는 인스턴스에 대한 충분한 정보 수집.

그런 다음 조건에 의해 트리거 된 전략적 위치에서 중단 점을 설정했습니다. 적절한 주소를 가진 인스턴스에 대해서만 또는 구성원에 특정 값으로 트리거하십시오.

증상은 정확하게 발생하지만 문제는 발생하지 않을 가능성이 높지만 여전히 문제가 있습니다.

희망이 도움이됩니다.

+0

이것은 흥미로운 접근 방법처럼 들리지만, 나는 미래의 디버깅 세션을 위해 그것을 명심해야 할 것이다! – Jonas

1

Running valgrind "4 크기의 유효하지 않은 읽기"가 표시됩니다. 이는 4 바이트의 카나리아 int를 읽었지만이 시점에서 이미 너무 늦었습니다.

당신은 혼란 : Valgrind의 당신이, 당신은 danging (이미 해제) 객체를 읽고 (객체가 해제 된 아마 때문에) 잘못된 읽기를하고있는 당신을 말한다면, 그것은 정확히당신의 문제.

이러한 개체에 액세스하려고하면 안되며 개체를 해제/삭제 한 후에도 사용자의 카나리아가 변경되었거나 손상된 사실과 관련이 없습니다.