힙 손상 오류가있는 큰 MFC 기반 응용 프로그램을 충돌시키는 테스트 사례가 있습니다.App Verifier 출력 해석 : 힙 손상 또는 스택 주소를 힙 주소로 잘못 해석 했습니까?
문제의 DLL에 대해 App Verifier를 사용하여 페이지 힙을 켰습니다 (불행히도 전체 프로세스에서 힙을 켜는 것은 다른 이유로는 유용하지 않습니다). 검증 프로그램은 우리가 제공하는 것보다 더 많은 정보를 제공하지 않았습니다. 이미 가지고 있었다; 그것은 원래의 충돌과 같은 시점에서 시작되었습니다.
지금 저는 두 가지 경쟁 이론을 가지고 있습니다. 어떤 이론이 옳을 것이라고 생각합니까? 그리고 다음 단계는 무엇이 될까요?
- 이것은 실제로 힙 손상입니다. Verifier가 다른 DLL에서 발생하기 때문에 원래 손상을 포착하지 않습니다. 우리는 더 많은 DLL에 대한 검증자를 활성화하고 어떤 코드가 힙을 손상시키는 지 결정해야합니다.
- 힙이 좋습니다. 문제는 스택 주소를 힙 주소로 처리한다는 것입니다. 우리는이 호출 스택의 코드를 자세히 조사하여 잘못된 점을 파악해야합니다.
free()에 대한 매개 변수가 스택 주소와 비슷해 보이지만 지금까지 아무도이 방법에 대한 설명을 제안하지 않았기 때문에 저는 # 2에 기울고 있습니다.
다음은 호출 스택 스 니펫입니다. MyString은 CString을 둘러싼 간단한 래퍼입니다. MyAppDll은 페이지 힙을 사용하도록 설정된 DLL입니다. 여기
msvcr90.dll!free(void * pBlock=0x000000000012d6e8) Line 110 mfc90u.dll!ATL::CStringT > >::~CStringT > >() Line 1011 + 0x1e bytes MyStringDll.dll!MyString::~MyString() Line 59 MyAppDll.dll!doStuffWithLotsOfStringInlining(MyClass* input=0x000000000012d6d0) Line 863 + 0x26 bytes는 무료() 스택 프레임 내부 레지스터입니다 :
RAX = 0000000000000000 RBX = 000000000012D6E8 RCX = 0000000000000000 RDX = 0000000000000000 RSI = 000000000012D6D0 RDI = 00000000253C1090 R8 = 0000000000000000 R9 = 0000000000000000 R10 = 0000000000000000 R11 = 0000000000000000 R12 = 000000000012D7D0 R13 = 000007FFFFC04CE0 R14 = 0000000025196600 R15 = 0000000000000000 RIP = 00000000725BC7BC RSP = 000000000012D570 RBP = 000007FFF3670900 EFL = 00000000
을 그리고 여기에 응용 프로그램 검증 메시지는 다음과 같습니다
VERIFIER STOP 0000000000000010: pid 0x1778: Corrupted start stamp for heap block. 00000000083B1000 : Heap handle used in the call. 000000006DD394E8 : Heap block involved in the operation. 54D32858A8747589 : Size of the heap block. 000000005E33BA8D : Corrupted stamp value.
감사합니다. 이것은 내가 찾던 답변입니다. 불행히도 여기에는 완전한 그림을 제공하기 위해 너무 많은 코드가 포함되어 있습니다. 짧은 발췌가 도움이 될 것이라고 생각하지 않습니다. – Dewb
x64 모드에서 호출 스택에 표시된대로 매개 변수 값을 신뢰할 수 없으면 레지스터에 전달됩니다. 이러한 레지스터 값은 오랫동안 덮어 썼습니다. RBP는 매우 불만스럽게 보입니다. –
문자열 래퍼 클래스가 MFC의 nil 문자열 데이터 singleton의 참조 횟수를 영구적으로 늘리는 결과를 초래 한 새로운 위치 지정으로 영리한 작업을 수행했다. 결국 (버그가있는 코드로 20 억 회를 호출 한 후) 참조 횟수가 오버플로되고 음수가되고 nil 버퍼가 삭제됩니다! 그런 다음 파괴 된 다음 빈 문자열에 이중 자유가 적용됩니다. – Dewb