우리 소프트웨어에서 이상한 충돌이 발생하고 디버깅하는 데 많은 어려움을 겪고 있습니다. 따라서 이 문제를 해결하는 방법에 대한 조언을 구하고 있습니다. $ 00CF0041에서유용한 호출 스택이없는 재생산하기 어려운 크래시를 어떻게 디버깅합니까?
첫 번째 예외 :
충돌은 NULL 포인터를 읽기 액세스 위반이다. 예외 클래스 $ C0000005 메시지가 '0x00cf0041에서 액세스 위반 : 주소 0x00000000의 읽기'.
'가끔'만 발생합니다. 나는 어떤 운이나 이유를 알아낼 수 없었지만, 언제나 메인 스레드에서만 가능합니다. 메인 스레드에 대한
,이 인은 다른 항목의 전체 큰 스택을 표시해야합니다 : 그것은 발생하면 호출 스택은 하나 개의 잘못된 항목이 포함되어 있습니다.
이 시점에서 다른 모든 스레드는 비활성 상태입니다 (주로 WaitForSingleObject
또는 이와 유사한 함수에 있음).이 충돌은 주 스레드에서만 발생하는 것으로 나타났습니다. 동일한 주소에서 동일한 메소드에서 항상 동일한 항목의 호출 스택을가집니다. 이 방법은 관련이있을 수도 있고 아닐 수도 있습니다. 우리는 우리의 어플리케이션에서 VCL을 사용합니다. 내 베팅은 스택 (stack)을 손상시키고있는 무언가 (아마도 꽤 오래 전부터)가 충돌하는 주소가 무작위 적이라는 것입니다. 하지만 여러 빌드에서 동일한 주소가 사용되었지만 실제로는 무작위가 아닐 수도 있습니다. 여기
- 가 특정 지점에서 안정적으로 재현하려고합니다. 나는 매번 그것을 재현하는 것을 발견하지 못했고, 명백한 이유가없는 가끔은 두 가지를하거나하지 않았다. 이것들은 코드의 특정 섹션으로 좁힐 수있는 충분한 '협의'액션이 아닙니다. 그것은 타이밍과 관련이있을 수 있지만, IDE가 깨지면 다른 스레드는 일반적으로 아무것도하지 않습니다. 스레딩 문제는 배제 할 수는 없지만 가능성은 희박하다고 생각합니다.
- 추가 디버깅 문으로 작성 (추가 디버그 정보, 추가 어설 션 등) 이렇게하면 충돌이 발생하지 않습니다.
- Codeguard이있는 건물. 이렇게하면 충돌이 발생하지 않으며 Codeguard는 오류를 표시하지 않습니다.
내 질문 :
1. 어떻게 충돌의 원인 코드를 찾을 수 있습니까? 스택을 걷는 것과 동일한 조치를 수행하려면 어떻게해야합니까?
2.이 충돌의 원인을 추적하는 방법에 대한 일반적인 조언은 무엇입니까? 내가 Embarcadero RAD Studio 2010을 사용하고
은 (프로젝트는 대부분 C++ 빌더 코드와 델파이의 소량이 포함되어 있습니다.)
편집 : 내가 실제로 원인을 추가해야합니다 생각했다. ReadDirectoryChangesW
을 호출 한 스레드가 있고 GetOverlappedResult
을 사용하여 계속 이벤트를 기다렸다가 변경 사항을 수행합니다.이벤트는 또한 상태 플래그를 설정 한 후 스레드를 종료하기 위해 신호를 보냈습니다. 문제는 스레드가 종료되었을 때 결코 CancelIO
을 호출하지 않는다는 것입니다. 결과적으로 Windows는 여전히 변경 내용을 추적하고 있었고 버퍼가 겹쳐진 구조와 이벤트가 더 이상 존재하지 않거나 (심지어는 만든 스레드 컨텍스트가 아니더라도) 디렉터리가 변경되었을 때 버퍼에 계속 쓰고있었습니다. CancelIO
이 호출되었을 때 , 더 이상의 충돌은 없었다.
저는 CodeGaurd에 익숙하지 않습니다. 스택 카나리아 및 유효성 검사도 소개합니까? 나는 C++과 Delphi를 혼합하고 있기 때문에 물어 봅니다 - 이것은 당신이 그것을 깨닫지 못하고 호출 규칙을 혼합 할 수 있음을 의미합니다. 그렇게하면 매우 빨리 스택을 망가뜨릴 수 있습니다.이 스택은 손상된 호출 스택이있는 메인 스레드에서 무작위로 충돌하는 것처럼 보입니다. –
Codeguard는 스택의 초기화되지 않은 부분을 바이트 패턴으로 채 웁니다. 또한 해제 된 메모리에 액세스하는 것, 할당 된 메모리에 오버런하는 것과 같은 것들을 확인하려고 시도합니다. 호출 규칙을 잘못 지정하면 분명히 이와 같은 문제가 발생할 수 있습니다 (예를 들어 제안에 감사드립니다). 그렇다면 어디에 있는지 잘 모릅니다. : C++ Builder는 Delphi 코드와 상호 운용되도록 설계되었으므로 선언 어딘가에서 오류를 만들어야하며 대부분 IDE 또는 컴파일러가 관리합니다. 중요한 질문은 다음과 같습니다. 잘못 선언 된 메소드를 찾는 방법은 무엇입니까? –
막연한 답변이기 때문에 다른 디버거를 사용해 볼 수도 있습니다. 예를 들어 WinDbg는 손상되거나 혼동 된 경우 실제 콜 스택을 재구성하기위한 힌트 (또는 모든 것)를 제공합니다. –