2013-09-26 7 views
1

나는 정상 페이지 힙 (가득 차 있지 않음)로 크래시 시나리오 (고립 된 테스트 응용 프로그램에서)를 테스트하려고한다.페이지 힙은 유용한 스택 정보를 기록하지 않습니다?

내가

gflags /p /enable Test.exe 

와 플래그를 설정하고 난 하나 개의 요소

... 
const size_t s = 100; 
vector<int> v1(s, 0); 
int* v1_base = &v1[0]; 
write_to_memory_int(v1_base, s+1); 
... 

실제로 블록이 벡터 디부 토르에서 해제하여 정수 버퍼를 덮어있어, 나는 휴식을 취한다. 휴식의 호출 스택이 제대로보고 : 나는 오류있는 할당 볼 때

0:005> kp 
    *** Stack trace for last set context - .thread/.cxr resets it 
ChildEBP RetAddr 
0785faa4 11229df2 verifier!VerifierStopMessage+0x1f8 
0785fb08 1122a22a verifier!AVrfpDphReportCorruptedBlock+0x1c2 
0785fb64 1122a742 verifier!AVrfpDphCheckNormalHeapBlock+0x11a 
0785fb84 112290d3 verifier!AVrfpDphNormalHeapFree+0x22 
0785fba8 77951564 verifier!AVrfDebugPageHeapFree+0xe3 
0785fbf0 7790ac29 ntdll!RtlDebugFreeHeap+0x2f 
0785fce4 778b34a2 ntdll!RtlpFreeHeap+0x5d 
0785fd04 750c14dd ntdll!RtlFreeHeap+0x142 
0785fd18 71fc4c39 kernel32!HeapFree+0x14 
0785fd64 00404b0a msvcr80!free(void * pBlock = 0x0726f7b8)+0xcd [f:\dd\vctools\crt_bld\self_x86\crt\src\free.c @ 110] 
0785fd90 00402ac7 Test!std::vector<int,std::allocator<int> >::_Tidy 
... 

그러나, 나는 단지 받기 :

입니다
0:005> !heap -p -a 0x0726f7b8 
    address 0726f7b8 found in 
    _HEAP @ 30000 
     HEAP_ENTRY Size Prev Flags UserPtr UserSize - state 
     0726f790 0039 0000 [00] 0726f7b8 00190 - (busy) 
     1122a6a7 verifier!AVrfpDphNormalHeapAllocate+0x000000d7 
     11228f6e verifier!AVrfDebugPageHeapAllocate+0x0000030e 
     77950d96 ntdll!RtlDebugAllocateHeap+0x00000030 
     7790af0d ntdll!RtlpAllocateHeap+0x000000c4 
     778b3cfe ntdll!RtlAllocateHeap+0x0000023a 

, 할당 스택 추적이 입니다, 그러나 그것은 완전히 쓸데없는 RtlAllocateHeap에 멈춘다.

메모리에 스택 추적을 보면 :

dt _DPH_BLOCK_INFORMATION ....-0x20 

=> 

0:005> dds 0x03e556f4 
03e556f4 00000000 
03e556f8 00002050 
03e556fc 00050000 
03e55700 1122a6a7 verifier!AVrfpDphNormalHeapAllocate+0xd7 
03e55704 11228f6e verifier!AVrfDebugPageHeapAllocate+0x30e 
03e55708 77950d96 ntdll!RtlDebugAllocateHeap+0x30 
03e5570c 7790af0d ntdll!RtlpAllocateHeap+0xc4 
03e55710 778b3cfe ntdll!RtlAllocateHeap+0x23a 
03e55714 00000000 
03e55718 00003001 
03e5571c 0004005e 

이 더 기록 된 사실 아무것도 존재하지 않은 것 같습니다.

유용한 스택 추적을 기록하기 위해 페이지 힙을 수정하려면 어떻게해야합니까?

테스트 프로젝트는 이 아니며 FPO (/ Oy)로 컴파일 된이 아니므로 RtlAllocateHeap은 FPO의 영향을 받겠습니까?


업데이트 : (아래 참조)는 VC80 (VS2005) 런타임 libs와 모두 malloc뿐만 아니라 op new 가지고있는 것으로 생각된다 수동으로 할당에 스테핑에 의해 문제의 호출의 FPO 다움을 확인 어떤 형태의 FPO가 가능 해지면 페이지 힙의 스택 DB에 대한 스택 추적을 엉망으로 만들 수 있습니다. 내가 진짜 할당 스택 트레이스를 체크 아웃해야한다 코멘트에 지적 @Marc 셔먼에

0:004> kv 
ChildEBP RetAddr Args to Child    
077efa7c 77c8af0d 05290000 01001002 00000190 ntdll!RtlDebugAllocateHeap+0x16 (FPO: [Non-Fpo]) 
077efb60 77c33cfe 00000190 00000000 00000000 ntdll!RtlpAllocateHeap+0xc4 (FPO: [Non-Fpo]) 
077efbe4 72344d83 05290000 01001002 00000190 ntdll!RtlAllocateHeap+0x23a (FPO: [Non-Fpo]) 
077efc04 62f595ee 00000190 00000000 00000000 MSVCR80!malloc+0x7a (FPO: [1,0,0]) (CONV: cdecl) 
077efc1c 00406a44 00000190 ebecf74f 00000001 MFC80U!operator new+0x2f (FPO: [Uses EBP] [1,0,0]) (CONV: cdecl) 
077efc48 00405479 00000064 00000000 3fffffff Test!std::_Allocate<ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > > >+0x84 (FPO: [Non-Fpo]) (CONV: cdecl) 
077efcb8 004049f4 00000064 ebecf68f 00000000 Test!std::vector<unsigned int,std::allocator<unsigned int> >::_Buy+0x69 (FPO: [Non-Fpo]) (CONV: thiscall) 
077efd88 00402a4f 00000064 077efdc0 ebecf44b Test!std::vector<int,std::allocator<int> >::_Construct_n+0x44 (FPO: [Non-Fpo]) (CONV: thiscall) 
077eff4c 72342848 00000000 ebec8474 00000000 Test!crashFN+0x35f (FPO: [Non-Fpo]) (CONV: cdecl) 
077eff84 723428c8 75da33aa 072ab3d8 077effd4 MSVCR80!_callthreadstart+0x1b (FPO: [Non-Fpo]) (CONV: cdecl) 
077eff88 75da33aa 072ab3d8 077effd4 77c39f72 MSVCR80!_threadstart+0x5a (FPO: [1,0,0]) (CONV: stdcall) 
077eff94 77c39f72 072ab3d8 70fca8b2 00000000 kernel32!BaseThreadInitThunk+0xe (FPO: [Non-Fpo]) 
077effd4 77c39f45 7234286e 072ab3d8 00000000 ntdll!__RtlUserThreadStart+0x70 (FPO: [Non-Fpo]) 
077effec 00000000 7234286e 072ab3d8 00000000 ntdll!_RtlUserThreadStart+0x1b (FPO: [Non-Fpo]) 

+0

는 아마 C++ 런타임 및/또는 CRT는 FPO 컴파일됩니다. 'dds 0x03e556f4 L80'으로 dds의 범위를 늘리면 어떨까요? 흥미로운 반송 주소가 보이십니까? –

+0

@Marc : 아니요, 첫 번째 stac (흥미 롭거나 관련이없는 스택)을 넘어 흥미로운 부분이없는 것처럼 보입니다. –

+0

게시 한 메모리의 해당 스택 추적에 관한 이상한 점은 해당 반환 주소가 서로 즉시 이어지는 것입니다. 일반적으로 저장된 EBP가 중간에 표시됩니다. 처음에 0x03e556f4 값을 어떻게 찾았습니까? –

답변

2

감사합니다. 앵커 검색하는 데,

MSVCR80!malloc+0x7a (FPO: [1,0,0]) (CONV: cdecl) 
MFC80U!operator new+0x2f (FPO: [Uses EBP] [1,0,0]) (CONV: cdecl) 

을 이제 우리는 : 그것은 CRT는 스택 추적에서 볼 수 있듯이 FPO이 활성화되어있어로

이 이미 질문에 편집, VC80 (VS2005)는 문제는 여기에있다

Why does every heap trace in UMDH get stuck at “malloc”?

추가 몇 따옴표 : 다음을 찾을 이상적 상대에

cular를 사용하면 Visual C++ 2005의 정적 링크 CRT에있는 기본 malloc 구현 이 프레임 포인터를 사용하지 않을뿐만 아니라 ebp를 스크래치 레지스터로 삭제합니다.

이게 무슨 의미입니까? 음, 으로 빌드 된 malloc을 사용하는 모든 것 Visual C++ 2005는 UMDH 또는 적어도이 x86 빌드가 아닌 ebp 기반 스택 추적에 의존하는 것으로 진단 할 수 없습니다.

좋은 정보를 가지고 코멘트에 회신도있다 :

마크 로버츠 [MSFT]를 말한다 : 오후 3시 3분

안녕하세요 2 월 (25) 2008,

8.0 CRT에 대해 FPO를 사용하도록 만든 것이 의도적 인 것이 아닙니다. Visual Studio 2008 CRT (9.0)에 FPO를 사용할 수 없으며 UMDH가 정상적으로 으로 작동해야합니다.

8.0의 경우 UMDH 대신 LeakDiag를 사용하는 것이 좋습니다. LeakDiag 은 스택 추적을 얻기 위해 실제로 메모리 할당자를 계측합니다. 다른 할당 자 유형을 다른 세분성 ( c 런타임에서 원시 가상 메모리 할당까지)에 연결할 수 있으므로 UMDH보다 다양한 용도로 사용할 수 있습니다.

기본적으로 LeakDiag는 스택 기본 포인터를 걷기 만하지만 은 FPO 데이터를 확인하기 위해 Dbghlp StackWalkAPI를 사용하도록 수정할 수 있습니다. 이 은 성능이 저하되지만 전체 스택을 생성합니다. 에서 플립면에서는 퍼커널 페널티를 최소화하기 위해 특정 깊이까지 만 이동하도록 스택 워킹 동작을 사용자 정의 할 수 있습니다.

여기 LeakDiag를 찾아주세요 : ftp://ftp.microsoft.com/PSS/Tools/Developer%20Support%20Tools/LeakDiag/leakdiag125.msi

+1

MSVC libs의 FPO는 여러 해 동안 반복되는 문제였습니다. 일반적으로 FPO가없는 디버그 버전을 실행하는 옵션이 있습니다 (그러나 버전은 확실하지 않음). –