Windbg内存泄漏问题的定位

文章目录

1、搭建环境

1.1 测试程序

这里的测试程序是很简单的那种,凑合着用吧

#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文件,如下:
Windbg内存泄漏问题的定位

1.2 设置pdb路径和源码路径

如何设置参考其他文章,这里不再说明

2、定位

2.1 运行程序

执行g命令:
Windbg内存泄漏问题的定位
发现程序很快就退出了,这时候运行分析命令,如下:

*******************************************************************************
*                                                                             *
*                        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,如下:
Windbg内存泄漏问题的定位
好像也没有我们的代码,这时候怎么办呢?

2.2 分析

2.2.1 查看一下堆栈分配情况

执行 !heap -s,如下:
Windbg内存泄漏问题的定位
只有一条信息,所以当然是分析这条信息了,如果存在很多条的话需要看分配最多的堆栈,如图红色框框的值,找出最大的几个值。

执行!heap -stat -h 00000000,如下:
Windbg内存泄漏问题的定位
如上图,找到了分配最多的堆栈块之后,可利用条件断点,获取分配该块内存时的栈信息。
设置断点如下:
Windbg内存泄漏问题的定位

bp ntdll!RtlAllocateHeap "j (poi(esp + c)=120) '';'gc'"                         // poi(esp + c) 表示取分配的堆块大小

之后执行g命令:
Windbg内存泄漏问题的定位
进程退出了,执行以下kv命令:
Windbg内存泄漏问题的定位
由上,我们就知道大概问题在哪了(虽然一开始看代码也知道),这个时候看一下提示附近的代码,发现一直在申请内存,但是没有释放操作,就很容易导致内存用完等情况的发生。

上一篇:原码,反码,补码


下一篇:判断一个数是否是2的N次幂