2012-06-26 2 views
2

여기 내 로프 끝에 있습니다. 단일 스레드 C++ 프로그램이 있습니다. 다음은 경험적 데이터와 배경 정보입니다. 가장 중요한 키워드를 강조했습니다.단일 스레드 C++ 함수 호출에서 undebuggable non-deterministic heisenbug

  • 제가 이야기 전체 섹션 는 (탈) 할당은 표준 C를 호출 ++ 라이브러리가 수행 할 수 메모리 이외의 콜 (std::set의 참여입니다)를 가지고 있지 않습니다. 순전히 논리적 인 알고리즘입니다.
  • 의 동작은 입력에 따라 결정적이어야하며, 나는 변하지 않습니다.
  • 버그가있는 경우 프로그램은 무한 루프처럼 보이는 데, 바운드를 초과하여 메모리를 할당하는 것 같습니다. .
  • 버그 하지 매니페스트 자체가 예측, 나는 때때로 명령 줄에서 프로그램을 실행할 수 있습니다 않습니다 (아마 30 % -50 %) 버그가 자체 명단 그렇지 않으면, 모든 I로까지 원활하고 제대로 실행 말할 수있다.
  • 일단 프롬프트에서 직접 실행하지 않고 gdb 또는 valgrind에서 프로그램을 실행하면 버그가 사라집니다., 프로그램이 종료되지 않습니다.
  • 이제는 가장 중요한 부분이 있습니다.이 문제는 (템플릿으로 된) 비회원 멤버 함수 호출으로 추적되었습니다. 전화 전에 으로 전화하면 std::cout으로 메시지가 출력됩니다.이 메시지는 입니다. 터미널에이 있습니다. 첫 번째 라인의에는 디버그 메시지가 있습니다. 을 표시하지 않았습니다.

나는 더 이상 합당한 설명을 볼 수 없다. 어쩌면 진행 방법을 생각해 낼 수 있습니다.


편집 : 우리는 그들과 생략 관련이없는 부분 참조 할 수 있도록 코드의 중요한 라인, 정말 모든 것이 최고의 이해하는 것, 줄 번호를 변경했습니다.

a.cpp

10  std::set<Array const*>* symbols; 
11  std::set<Array const*> allSymbols; 
12  symbols = &allSymbols; 
// ... allSymbols are populated with std::inserter 
15  std::cout << "eval; cd = " << &cd << ", cg = " << &cd.cg << std::endl; 
16  senderConstraints = cd.cg.eval(*symbols); 

b.cpp

31  template <typename ArrayContainer> 
32  ConstraintList eval(ArrayContainer const request) { 
33  std::cout << "inside eval ... going to update graph now" << std::endl; 

출력의 마지막 줄은 다음과 같습니다

eval; cd = 0x2e6ebb0, cg = 0x2e6ebc0 

는 그 다음이 무한 루프에 갇혀.

+0

이것이 정말로 경쟁 조건이 아니라고 확신하는 경우 (효과는 사용자가 묘사 한 것과 똑같이 보입니다), 내 상태를 덤프하여 어떤 상태가 버그 상태가되는지 확인합니다. 일부 잘못된 초기화 순서로 인해 이러한 동작이 발생할 수도 있습니다. –

+7

코드가 도움이됩니다. 그렇지 않으면 아무 것도 말하기가 불가능합니다. 그러나 "버그는 마술처럼 디버거에서 사라졌습니다"는 보통'if (ptr! = NULL) do_something();의 별자리를 가리 킵니다. '및 초기화되지 않은 변수를 포함합니다. 실수로 메모리 위치가 0이면 버그가 발생하지 않으며 그렇지 않은 경우 버그가 발생합니다. 디버거는 ** 모든 ** 변수를 초기화합니다 (그렇지 않은 경우라도). 따라서 버그는 "마술처럼 사라졌습니다". – Damon

+0

['strace'] (http://linux.die.net/man/1/strace)를 사용하여 시스템 호출을 추적 할 수 있습니다 (일부는 시스템 라이브러리 내부에 숨겨져있을 수 있습니다). 또한 디버그 인쇄 ** lot ** **을 추가하는 것이 좋습니다. –

답변

5

는 나도 allSymbols의 상태가 라인 12 라인 15, 또는 사이 손상, 당신은

ConstraintList eval(ArrayContainer const request) 

ConstraintList eval(ArrayContainer const & request) 

그렇다면 변경할 때, 두 번째 줄이 인쇄 내기 코드는 정말 더 다음과 같습니다

문자가 alre을 참조하기 때문에, UB입니다
std::set<Array const*>* symbols; 
{ 
    std::set<Array const*> allSymbols; 
    symbols = &allSymbols; 
    // ... allSymbols are populated with std::inserter 
} 
std::cout << "eval; cd = " << &cd << ", cg = " << &cd.cg << std::endl; 
senderConstraints = cd.cg.eval(*symbols); 

ady destructed 오브젝트.

+0

예, 나는 눈이 멀었습니다, 미안 해요. 좋은 추측. 내 방어하지만, 실제 일이 좀 더 복잡해 보입니다. – bitmask

관련 문제