这里的测试程序是很简单的那种,凑合着用吧
#include "stdafx.h" void LeakMem() { while (true) { char *pTest = new char[512]; } } int _tmain(int argc, _TCHAR* argv[]) { LeakMem(); system("pause"); return 0; }
编译好了之后,使用WinDbg打开这个exe文件,如下:
如何设置参考其他文章,这里不再说明
执行g命令:
发现程序很快就退出了,这时候运行分析命令,如下:
******************************************************************************* * * * Exception Analysis * * * ******************************************************************************* FAULTING_IP: ntdll_77a90000!LdrpDoDebuggerBreak+2b 77b3ed22 cc int 3 EXCEPTION_RECORD: ffffffffffffffff -- (.exr 0xffffffffffffffff) ExceptionAddress: 0000000077b3ed22 (ntdll_77a90000!LdrpDoDebuggerBreak+0x000000000000002b) ExceptionCode: 4000001f (WOW64 breakpoint) ExceptionFlags: 00000000 NumberParameters: 1 Parameter[0]: 0000000000000000 CONTEXT: 0000000000000000 -- (.cxr 0x0;r) eax=00000000 ebx=00b69000 ecx=77ae0000 edx=00000000 esi=00f51b70 edi=77a9687c eip=77b3ed22 esp=00cff57c ebp=00cff5a8 iopl=0 nv up ei pl zr na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246 ntdll_77a90000!LdrpDoDebuggerBreak+0x2b: 77b3ed22 cc int 3 FAULTING_THREAD: 00000000000037cc PROCESS_NAME: testC.exe ERROR_CODE: (NTSTATUS) 0x4000001f - Win32 x86 EXCEPTION_CODE: (NTSTATUS) 0x4000001f (1073741855) - Win32 x86 EXCEPTION_PARAMETER1: 0000000000000000 NTGLOBALFLAG: 70 APPLICATION_VERIFIER_FLAGS: 0 APP: testc.exe ANALYSIS_VERSION: 6.3.9600.17237 (debuggers(dbg).140716-0327) amd64fre BUGCHECK_STR: APPLICATION_FAULT_APPLICATION_FAULT_ZEROED_STACK PRIMARY_PROBLEM_CLASS: APPLICATION_FAULT DEFAULT_BUCKET_ID: APPLICATION_FAULT LAST_CONTROL_TRANSFER: from 0000000077b394e6 to 0000000077b3ed22 STACK_TEXT: 00cff5a8 77b394e6 f2b3a2ed 00b69000 00000000 ntdll_77a90000!LdrpDoDebuggerBreak+0x2b 00cff808 77ac2fe1 f2b3a285 00000000 00000000 ntdll_77a90000!LdrpInitializeProcess+0x1ba6 00cff860 77ac2ed1 00000000 00000000 00000000 ntdll_77a90000!_LdrpInitialize+0xba 00cff86c 00000000 00cff880 77a90000 00000000 ntdll_77a90000!LdrInitializeThunk+0x11 STACK_COMMAND: dt ntdll!LdrpLastDllInitializer BaseDllName ; dt ntdll!LdrpFailureData ; .cxr 0x0 ; kb FOLLOWUP_IP: ntdll_77a90000!LdrpDoDebuggerBreak+2b 77b3ed22 cc int 3 SYMBOL_STACK_INDEX: 0 SYMBOL_NAME: ntdll!LdrpDoDebuggerBreak+2b FOLLOWUP_NAME: MachineOwner MODULE_NAME: ntdll_77a90000 IMAGE_NAME: ntdll.dll DEBUG_FLR_IMAGE_TIMESTAMP: 35191cc1 FAILURE_BUCKET_ID: APPLICATION_FAULT_4000001f_ntdll.dll!LdrpDoDebuggerBreak BUCKET_ID: APPLICATION_FAULT_APPLICATION_FAULT_ZEROED_STACK_ntdll!LdrpDoDebuggerBreak+2b ANALYSIS_SOURCE: UM FAILURE_ID_HASH_STRING: um:application_fault_4000001f_ntdll.dll!ldrpdodebuggerbreak FAILURE_ID_HASH: {3541e160-89f9-c3a5-892f-80a0fe512d28} Followup: MachineOwner ---------
由上,并没有提示要执行的命令,接下来执行以下kv,如下:
好像也没有我们的代码,这时候怎么办呢?
执行 !heap -s,如下:
只有一条信息,所以当然是分析这条信息了,如果存在很多条的话需要看分配最多的堆栈,如图红色框框的值,找出最大的几个值。
执行!heap -stat -h 00000000,如下:
如上图,找到了分配最多的堆栈块之后,可利用条件断点,获取分配该块内存时的栈信息。
设置断点如下:
bp ntdll!RtlAllocateHeap "j (poi(esp + c)=120) '';'gc'" // poi(esp + c) 表示取分配的堆块大小
之后执行g命令:
进程退出了,执行以下kv命令:
由上,我们就知道大概问题在哪了(虽然一开始看代码也知道),这个时候看一下提示附近的代码,发现一直在申请内存,但是没有释放操作,就很容易导致内存用完等情况的发生。