Advanced Debugging
About AdvDbg Consult Train Services Products Tools Community Contact  
欢迎光临 高端调试 登录 | 注册 | FAQ
 
  ACPI调试
Linux内核调试
Windows内核调试
 
  调试战役
调试原理
新工具观察
 
  Linux
Windows Vista
Windows
 
  Linux驱动
WDF
WDM
 
  PCI Express
PCI/PCI-X
USB
无线通信协议
 
  64位CPU
ARM
IA-32
  CPU Info Center
 
  ACPI标准
系统认证
Desktop
服务器
 
  Embedded Linux
嵌入式开发工具
VxWorks
WinCE
嵌入式Windows
 
  格蠹调试套件(GDK)
  格蠹学院
  小朱书店
  老雷的微博
  《软件调试》
  《格蠹汇编》
  《软件调试(第二版)》
沪ICP备11027180号-1

WinDbg

帖子发起人: hyqhero   发起时间: 2013-05-26 13:38 下午   回复: 6

Print Search
帖子排序:    
   2013-05-26, 13:38 下午
hyqhero 离线,最后访问时间: 2020/12/23 0:35:50 hyqhero

发帖数前150位
注册: 2013-04-26
发 贴: 8
使用umdh分析内存泄漏的疑惑,请张老师或其它大侠给予一些指点,万分感谢!
Reply Quote

问题1:请问使用umdh分析内存泄漏时最重要的注意事项是什么(是不是我哪个地方的设置不对,或符号文件的事)?---之所以这么问是因为~我感觉分析出来的结果(栈回溯)一部分看起来不太准确,例如我的exe并没有调用一个第三库的函数(接口),却显示出这个库中有内存泄漏。。。

问题2:如果我的程序中有一个切换的逻辑,也就是说因为可能会出现“申请-释放-申请....”,(当然这种机制下我们使用了内存池),在什么时机用umdh抓取内存状态会更合适呢?因为我发现我隔几分钟抓取内存的对比结果都不太一样。例如:一个小时间抓一个内存状态1.txt,再过1个小时之后,抓一个内存状态2.txt,对比较这两个文件发现总共(total)涨了1M的内存,但是!!再过1分钟我再抓内存,发现变成降了100k的内存了,(从任务管理器内看虚拟内存和专用工作集都是涨的状态),这是怎么回事啊?是不是我抓的时机不对,是不是应该把程序停下来再抓?

问题3:用umdh对比出来的内存泄漏为什么与任务管理器中显示的不太一样呢,如果对比发现总共涨了1M,任务管理器中看到却是2M或者更多(虚拟内存和专用工作集)。。问题是任务管理器中哪个列(虚拟内存or专用工作集or“其它”)的涨幅才是真正的能跟umdh中显示的对应一致上呢?

-------我的问题很多,非常感谢能够帮忙我们的人,虽然我们不曾见面,也没有报酬,但我想有很多默默伸出援手的人在这里,我们会永远地记住帮忙过我们的人,祝您一生快乐、平安。


IP 地址: 已记录   报告
   2013-05-26, 20:03 下午
Raymond 离线,最后访问时间: 2020/7/3 3:40:25 格蠹老雷

发帖数前10位
注册: 2005-12-19
发 贴: 1,303
Re: 使用umdh分析内存泄漏的疑惑,请张老师或其它大侠给予一些指点,什么感谢!
Reply Quote

不怕问题多,但是要精确,因为泛泛而谈可能张冠李戴,毫无意义......

拿出一个例子,copy, paste实际数据...

 


IP 地址: 已记录   报告
   2013-06-03, 16:48 下午
hyqhero 离线,最后访问时间: 2020/12/23 0:35:50 hyqhero

发帖数前150位
注册: 2013-04-26
发 贴: 8
Re: 使用umdh分析内存泄漏的疑惑,请张老师或其它大侠给予一些指点,什么感谢!
Reply Quote

下面是我们在一个项目中使用umdh抓取的栈回溯信息

 

+  650160 ( 1160880 - 510720)  13820 allocs BackTrace31A74AA0
+    7740 (  13820 -   6080) BackTrace31A74AA0 allocations

 ntdll!EtwSetMark+0000244D
 KERNELBASE!LocalAlloc+00000058
 nslook!CNoTrackObject::operator new+00000010 (f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\afxtls.cpp, 78)
 nslook!CThreadLocal<AFX_MODULE_THREAD_STATE>::CreateObject+00000007 (f:\dd\vctools\vc7libs\ship\atlmfc\include\afxtls_.h, 198)
 nslook!CThreadLocal<AFX_MODULE_THREAD_STATE>::GetData+0000000A (f:\dd\vctools\vc7libs\ship\atlmfc\include\afxtls_.h, 178)
 nslook!__DllMainCRTStartup+0000006C (f:\dd\vctools\crt_bld\self_x86\crt\src\dllcrt0.c, 318)
 nslook!_DllMainCRTStartup+0000001E (f:\dd\vctools\crt_bld\self_x86\crt\src\dllcrt0.c, 281)
 ntdll!wcsncmp+0000004C
 ntdll!LdrShutdownThread+000000E2
 ntdll!RtlExitUserThread+0000002A
 PlaySdkM4!_endthreadex+0000004A (f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c, 414)
 PlaySdkM4!_callthreadstartex+00000059 (f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c, 348)
 PlaySdkM4!_threadstartex+000000A4 (f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c, 331)

+  650160 ( 1160880 - 510720)  13820 allocs BackTrace31A72D8C
+    7740 (  13820 -   6080) BackTrace31A72D8C allocations

 ntdll!EtwSetMark+0000244D
 KERNELBASE!LocalAlloc+00000058
 NVDSDK!DEC_ClientSetMsgCallback+000179EE
 NVDSDK!DEC_ClientSetMsgCallback+00017380
 NVDSDK!DEC_ClientSetMsgCallback+00017454
 NVDSDK!DEC_ClientSetMsgCallback+00022A2E
 NVDSDK!DEC_ClientSetMsgCallback+00022AD6
 ntdll!wcsncmp+0000004C
 ntdll!LdrShutdownThread+000000E2
 ntdll!RtlExitUserThread+0000002A
 PlaySdkM4!_endthreadex+0000004A (f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c, 414)
 PlaySdkM4!_callthreadstartex+00000059 (f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c, 348)
 PlaySdkM4!_threadstartex+000000A4 (f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c, 331)

+  123840 ( 221056 -  97216)  13816 allocs BackTrace31A749B8
+    7740 (  13816 -   6076) BackTrace31A749B8 allocations

 ntdll!EtwSetMark+0000244D
 KERNELBASE!LocalAlloc+00000058
 nslook!CNoTrackObject::operator new+00000010 (f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\afxtls.cpp, 78)
 nslook!CThreadSlotData::SetValue+0000007C (f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\afxtls.cpp, 291)
 nslook!CThreadLocalObject::GetData+00000080 (f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\afxtls.cpp, 432)
 nslook!AfxGetModuleState+0000000F (f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\afxstate.cpp, 456)
 nslook!__DllMainCRTStartup+0000006C (f:\dd\vctools\crt_bld\self_x86\crt\src\dllcrt0.c, 318)
 nslook!_DllMainCRTStartup+0000001E (f:\dd\vctools\crt_bld\self_x86\crt\src\dllcrt0.c, 281)
 ntdll!wcsncmp+0000004C
 ntdll!LdrShutdownThread+000000E2
 ntdll!RtlExitUserThread+0000002A
 PlaySdkM4!_endthreadex+0000004A (f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c, 414)
 PlaySdkM4!_callthreadstartex+00000059 (f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c, 348)
 PlaySdkM4!_threadstartex+000000A4 (f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c, 331)

+  123840 ( 221104 -  97264)  13819 allocs BackTrace31A72CA4
+    7740 (  13819 -   6079) BackTrace31A72CA4 allocations

 ntdll!EtwSetMark+0000244D
 KERNELBASE!LocalAlloc+00000058
 NVDSDK!DEC_ClientSetMsgCallback+000179EE
 NVDSDK!DEC_ClientSetMsgCallback+00017E3F
 NVDSDK!DEC_ClientSetMsgCallback+00018086
 NVDSDK!DEC_ClientSetMsgCallback+00017969
 NVDSDK!DEC_ClientSetMsgCallback+00022A2E
 NVDSDK!DEC_ClientSetMsgCallback+00022AD6
 ntdll!wcsncmp+0000004C
 ntdll!LdrShutdownThread+000000E2
 ntdll!RtlExitUserThread+0000002A
 PlaySdkM4!_endthreadex+0000004A (f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c, 414)
 PlaySdkM4!_callthreadstartex+00000059 (f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c, 348)
 PlaySdkM4!_threadstartex+000000A4 (f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c, 331)

+   92880 ( 165816 -  72936)  13818 allocs BackTrace31A72D38
+    7740 (  13818 -   6078) BackTrace31A72D38 allocations

 ntdll!EtwSetMark+0000244D
 KERNELBASE!LocalAlloc+00000058
 NVDSDK!DEC_ClientSetMsgCallback+00017E33
 NVDSDK!DEC_ClientSetMsgCallback+00018086
 NVDSDK!DEC_ClientSetMsgCallback+00017969
 NVDSDK!DEC_ClientSetMsgCallback+00022A2E
 NVDSDK!DEC_ClientSetMsgCallback+00022AD6
 ntdll!wcsncmp+0000004C
 ntdll!LdrShutdownThread+000000E2
 ntdll!RtlExitUserThread+0000002A
 PlaySdkM4!_endthreadex+0000004A (f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c, 414)
 PlaySdkM4!_callthreadstartex+00000059 (f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c, 348)
 PlaySdkM4!_threadstartex+000000A4 (f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c, 331)

+   92880 ( 165828 -  72948)  13819 allocs BackTrace31A74A4C
+    7740 (  13819 -   6079) BackTrace31A74A4C allocations

 ntdll!EtwSetMark+0000244D
 KERNELBASE!LocalAlloc+00000058
 nslook!CThreadSlotData::SetValue+00000070 (f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\afxtls.cpp, 310)
 nslook!CThreadLocalObject::GetData+00000080 (f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\afxtls.cpp, 432)
 nslook!AfxGetModuleState+0000000F (f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\afxstate.cpp, 456)
 nslook!__DllMainCRTStartup+0000006C (f:\dd\vctools\crt_bld\self_x86\crt\src\dllcrt0.c, 318)
 nslook!_DllMainCRTStartup+0000001E (f:\dd\vctools\crt_bld\self_x86\crt\src\dllcrt0.c, 281)
 ntdll!wcsncmp+0000004C
 ntdll!LdrShutdownThread+000000E2
 ntdll!RtlExitUserThread+0000002A
 PlaySdkM4!_endthreadex+0000004A (f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c, 414)
 PlaySdkM4!_callthreadstartex+00000059 (f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c, 348)
 PlaySdkM4!_threadstartex+000000A4 (f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c, 331)

这是内存涨得最多的几个栈信息,都是调到了我们项目中的一个库PlaysdkM4调到了ntdll 再从ntdll调回我们项目中没有使用的库,很奇怪。

而且更匪夷所思的是_beginthreadex这个函数涨内存,上网查了可能是和tiddata结构体有关,我们还特地在线程中直接返回0并在线程退出前显式的调用_endthreadex(0)内存仍然涨在这。

上面贴的栈是没有调_endthreadex的


IP 地址: 已记录   报告
   2013-06-03, 19:53 下午
hyqhero 离线,最后访问时间: 2020/12/23 0:35:50 hyqhero

发帖数前150位
注册: 2013-04-26
发 贴: 8
Crying [:'(] Re: 使用umdh分析内存泄漏的疑惑,请张老师或其它大侠给予一些指点,什么感谢!
Reply Quote

下面是我刚刚抓的显示调用_endthreadex(0)umdp 2小时后对比的结果,和上面几乎一样,nslook和nvdsdk在老化过程总没用逻辑调用到。而且更不可能从ntdll调上来。

 

+ 6436080 ( 7081200 - 645120)  84300 allocs BackTrace2E883B60
+   76620 (  84300 -   7680) BackTrace2E883B60 allocations

 ntdll!RtlAllocateHeap+00000274
 KERNELBASE!LocalAlloc+0000005F
 nslook!CNoTrackObject::operator new+00000010 (f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\afxtls.cpp, 78)
 nslook!CThreadLocal<AFX_MODULE_THREAD_STATE>::CreateObject+00000007 (f:\dd\vctools\vc7libs\ship\atlmfc\include\afxtls_.h, 198)
 nslook!CThreadLocal<AFX_MODULE_THREAD_STATE>::GetData+0000000A (f:\dd\vctools\vc7libs\ship\atlmfc\include\afxtls_.h, 178)
 nslook!__DllMainCRTStartup+0000006C (f:\dd\vctools\crt_bld\self_x86\crt\src\dllcrt0.c, 318)
 nslook!_DllMainCRTStartup+0000001E (f:\dd\vctools\crt_bld\self_x86\crt\src\dllcrt0.c, 281)
 ntdll!LdrpCallInitRoutine+00000014
 ntdll!LdrShutdownThread+000000E6
 ntdll!RtlExitUserThread+0000002A
 PlaySdkM4!_endthreadex+0000004A (f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c, 414)
 PlaySdkM4!PlayThreadtest+0000000A (f:\windows sdk\windows\playsdkm4\trunk\source\sourcecode\player\player.cpp, 669)
 PlaySdkM4!_callthreadstartex+00000053 (f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c, 348)
 PlaySdkM4!_threadstartex+000000A4 (f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c, 331)

+ 6436080 ( 7081200 - 645120)  84300 allocs BackTrace2E8819CC
+   76620 (  84300 -   7680) BackTrace2E8819CC allocations

 ntdll!RtlAllocateHeap+00000274
 KERNELBASE!LocalAlloc+0000005F
 NVDSDK!DEC_ClientSetMsgCallback+000179EE
 NVDSDK!DEC_ClientSetMsgCallback+00017380
 NVDSDK!DEC_ClientSetMsgCallback+00017454
 NVDSDK!DEC_ClientSetMsgCallback+00022A2E
 NVDSDK!DEC_ClientSetMsgCallback+00022AD6
 ntdll!LdrpCallInitRoutine+00000014
 ntdll!LdrShutdownThread+000000E6
 ntdll!RtlExitUserThread+0000002A
 PlaySdkM4!_endthreadex+0000004A (f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c, 414)
 PlaySdkM4!PlayThreadtest+0000000A (f:\windows sdk\windows\playsdkm4\trunk\source\sourcecode\player\player.cpp, 669)
 PlaySdkM4!_callthreadstartex+00000053 (f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c, 348)
 PlaySdkM4!_threadstartex+000000A4 (f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c, 331)

+ 1225728 ( 1348576 - 122848)  84286 allocs BackTrace2E883A38
+   76608 (  84286 -   7678) BackTrace2E883A38 allocations

 ntdll!RtlAllocateHeap+00000274
 KERNELBASE!LocalAlloc+0000005F
 nslook!CNoTrackObject::operator new+00000010 (f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\afxtls.cpp, 78)
 nslook!CThreadSlotData::SetValue+0000007C (f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\afxtls.cpp, 291)
 nslook!CThreadLocalObject::GetData+00000080 (f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\afxtls.cpp, 432)
 nslook!AfxGetModuleState+0000000F (f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\afxstate.cpp, 456)
 nslook!__DllMainCRTStartup+0000006C (f:\dd\vctools\crt_bld\self_x86\crt\src\dllcrt0.c, 318)
 nslook!_DllMainCRTStartup+0000001E (f:\dd\vctools\crt_bld\self_x86\crt\src\dllcrt0.c, 281)
 ntdll!LdrpCallInitRoutine+00000014
 ntdll!LdrShutdownThread+000000E6
 ntdll!RtlExitUserThread+0000002A
 PlaySdkM4!_endthreadex+0000004A (f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c, 414)
 PlaySdkM4!PlayThreadtest+0000000A (f:\windows sdk\windows\playsdkm4\trunk\source\sourcecode\player\player.cpp, 669)
 PlaySdkM4!_callthreadstartex+00000053 (f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c, 348)
 PlaySdkM4!_threadstartex+000000A4 (f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c, 331)

+ 1225728 ( 1348576 - 122848)  84286 allocs BackTrace2E8818A4
+   76608 (  84286 -   7678) BackTrace2E8818A4 allocations

 ntdll!RtlAllocateHeap+00000274
 KERNELBASE!LocalAlloc+0000005F
 NVDSDK!DEC_ClientSetMsgCallback+000179EE
 NVDSDK!DEC_ClientSetMsgCallback+00017E3F
 NVDSDK!DEC_ClientSetMsgCallback+00018086
 NVDSDK!DEC_ClientSetMsgCallback+00017969
 NVDSDK!DEC_ClientSetMsgCallback+00022A2E
 NVDSDK!DEC_ClientSetMsgCallback+00022AD6
 ntdll!LdrpCallInitRoutine+00000014
 ntdll!LdrShutdownThread+000000E6
 ntdll!RtlExitUserThread+0000002A
 PlaySdkM4!_endthreadex+0000004A (f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c, 414)
 PlaySdkM4!PlayThreadtest+0000000A (f:\windows sdk\windows\playsdkm4\trunk\source\sourcecode\player\player.cpp, 669)
 PlaySdkM4!_callthreadstartex+00000053 (f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c, 348)
 PlaySdkM4!_threadstartex+000000A4 (f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c, 331)

+  919332 ( 1011456 -  92124)  84288 allocs BackTrace2E881938
+   76611 (  84288 -   7677) BackTrace2E881938 allocations

 ntdll!RtlAllocateHeap+00000274
 KERNELBASE!LocalAlloc+0000005F
 NVDSDK!DEC_ClientSetMsgCallback+00017E33
 NVDSDK!DEC_ClientSetMsgCallback+00018086
 NVDSDK!DEC_ClientSetMsgCallback+00017969
 NVDSDK!DEC_ClientSetMsgCallback+00022A2E
 NVDSDK!DEC_ClientSetMsgCallback+00022AD6
 ntdll!LdrpCallInitRoutine+00000014
 ntdll!LdrShutdownThread+000000E6
 ntdll!RtlExitUserThread+0000002A
 PlaySdkM4!_endthreadex+0000004A (f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c, 414)
 PlaySdkM4!PlayThreadtest+0000000A (f:\windows sdk\windows\playsdkm4\trunk\source\sourcecode\player\player.cpp, 669)
 PlaySdkM4!_callthreadstartex+00000053 (f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c, 348)
 PlaySdkM4!_threadstartex+000000A4 (f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c, 331)

+  919308 ( 1011444 -  92136)  84287 allocs BackTrace2E883ACC
+   76609 (  84287 -   7678) BackTrace2E883ACC allocations

 ntdll!RtlAllocateHeap+00000274
 KERNELBASE!LocalAlloc+0000005F
 nslook!CThreadSlotData::SetValue+00000070 (f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\afxtls.cpp, 310)
 nslook!CThreadLocalObject::GetData+00000080 (f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\afxtls.cpp, 432)
 nslook!AfxGetModuleState+0000000F (f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\afxstate.cpp, 456)
 nslook!__DllMainCRTStartup+0000006C (f:\dd\vctools\crt_bld\self_x86\crt\src\dllcrt0.c, 318)
 nslook!_DllMainCRTStartup+0000001E (f:\dd\vctools\crt_bld\self_x86\crt\src\dllcrt0.c, 281)
 ntdll!LdrpCallInitRoutine+00000014
 ntdll!LdrShutdownThread+000000E6
 ntdll!RtlExitUserThread+0000002A
 PlaySdkM4!_endthreadex+0000004A (f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c, 414)
 PlaySdkM4!PlayThreadtest+0000000A (f:\windows sdk\windows\playsdkm4\trunk\source\sourcecode\player\player.cpp, 669)
 PlaySdkM4!_callthreadstartex+00000053 (f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c, 348)
 PlaySdkM4!_threadstartex+000000A4 (f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c, 331)


IP 地址: 已记录   报告
   2013-06-04, 09:58 上午
houlin2012 离线,最后访问时间: 2013/6/4 1:56:50 嘻哈

发帖数前500位
注册: 2013-06-04
发 贴: 2
Re: 使用umdh分析内存泄漏的疑惑,请张老师或其它大侠给予一些指点,什么感谢!
Reply Quote

每个DLL都可以有一个入口点函数DllMain,系统会在不同的时刻调用此函数。以下是DllMain的一般形式:

BOOL WINAPI DllMain(
    HINSTANCE hinstDLL,  // handle to DLL module
    DWORD fdwReason,     // reason for calling function
    LPVOID lpReserved )  // reserved
{
    // Perform actions based on the reason for calling.
    switch( fdwReason ) 
    { 
        case DLL_PROCESS_ATTACH:
         // Initialize once for each new process.
         // Return FALSE to fail DLL load.
            break;

        case DLL_THREAD_ATTACH:
         // Do thread-specific initialization.
            break;

        case DLL_THREAD_DETACH:
         // Do thread-specific cleanup.
            break;

        case DLL_PROCESS_DETACH:
         // Perform any necessary cleanup.
            break;
    }
    return TRUE;  // Successful DLL_PROCESS_ATTACH.
}
以上代码摘自MSDN,几乎所有的DllMain都以这种形式呈现。
先来看一下这个函数传递进来的参数:
1、 HINSTANCE hinstDLL
这个参数是该DLL实例的句柄,也就是此DLL映射到进程地址空间后,在该进程地址空间中的位置。
2、 DWORD fdwReason
此参数标示了调用DllMain函数的原因。有四种值,就是函数中case后的取值。各个取值的含义,稍后论述。
3、 LPVOID lpReserved 
保留。
现在我们来讨论一下fdwReason的四种取值,这些取值,也直接反映了操作系统会在何种情况下调用DllMain。
1、DLL_PROCESS_ATTACH
当系统第一次将一个DLL映射到进程地址空间中时,会调用DllMain,并为fdwReason传入DLL_PROCESS_ATTACH。
注意,只有在第一次映射的时候,才会这样。如之后,另一线程再次显式加载此DLL,则操作系统只是增加该DLL的使用计数,而不会再次使用DLL_PROCESS_ATTACH来调用DllMain。
对DLL_PROCESS_ATTACH的处理,代表了DLL的初始化。
DllMain的返回值,也是针对DLL_PROCESS_ATTACH消息的。对于其余的三种取值,不起作用。
对于隐式加载,如DllMain返回FALSE,则程序会启动失败。对于显式加载,则会使LoadLibrary返回NULL。
2、DLL_PROCESS_DETACH
当系统将一个DLL从进程地址空间中撤销映射时,则会向DllMain传入DLL_PROCESS_DETACH。我们应当在此处放置一些清理代码。
当使用FreeLibrary时,如该线程的使用计数为0时,操作系统才会使用DLL_PROCESS_DETACH来调用DllMain。如使用计数大于0,则只是单纯的减少该DLL的计数。
3、DLL_THREAD_ATTACH
当进程创建一个线程,则系统会检查当前已映射到该进程空间中的所有DLL映像,并用DLL_THREAD_ATTACH来调用每个DLL的DllMain。
只有当所有DLL都完成了对DLL_THREAD_ATTACH的处理后,新线程才会执行它的线程函数。
另外,主线程不可能用DLL_THREAD_ATTACH来调用DllMain,因为主线程必然是在进程初始化的时候,用DLL_PROCESS_ATTACH调用DllMain的。
4、DLL_THREAD_DETACH
线程若要终止,会调用ExitThread,但是此函数不会立即终止线程,而是会利用DLL_THREAD_DETACH来调用当前进程地址空间中的所有DLL镜像的DllMain.
当每个DLL的DllMain都处理完后,系统才会真正的结束线程。
最后看一下DllMain的序列化调用
举个例子:
进程中有两个线程,A与B。进程的地址空间中,映射了一个名为SomeDll.dll的DLL。两个线程都准备通过CreateThread来创建另两个线程,C和D。
当线程A调用CreateThread来创建线程C的时候,系统会用DLL_THREAD_ATTACH来调用SomeDll.dll的DllMain,当线程C执行其中代码的时候,线程B调用CreateThread来创建线程D。
这时,系统同样会用DLL_THREAD_ATTACH来调用SomeDll.dll的DllMain,这次是让线程D来执行其中的代码。
但是此时,系统会对DllMain执行序列化,它会将线程D挂起,直至线程C执行完DllMain中的代码返回为止。
当C线程执行完DllMain中的代码并返回时,可以继续执行C的线程函数。此时,系统会唤醒线程D,让D执行DllMain中的代码。当返回后,线程D开始执行线程函数。

IP 地址: 已记录   报告
   2013-06-04, 10:00 上午
houlin2012 离线,最后访问时间: 2013/6/4 1:56:50 嘻哈

发帖数前500位
注册: 2013-06-04
发 贴: 2
Re: 使用umdh分析内存泄漏的疑惑,请张老师或其它大侠给予一些指点,什么感谢!
Reply Quote

张老师,现在的疑惑是nslook和nvdsdk都没有显式的dllmain函数,DLL_THREAD_ATTACH和DLL_THREAD_DETACH是怎样的?

 


IP 地址: 已记录   报告
   2013-06-04, 22:09 下午
Raymond 离线,最后访问时间: 2020/7/3 3:40:25 格蠹老雷

发帖数前10位
注册: 2005-12-19
发 贴: 1,303
Re: 使用umdh分析内存泄漏的疑惑,请张老师或其它大侠给予一些指点,什么感谢!
Reply Quote

如果用户代码没有写DllMain,那么编译器会使用dummy的DllMain,CRT源代码中可以找到:

比如C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\crt\src\


BOOL WINAPI DllMain(
        HANDLE  hDllHandle,
        DWORD   dwReason,
        LPVOID  lpreserved
        )
{
#if defined (CRTDLL)
        if ( dwReason == DLL_PROCESS_ATTACH && ! _pRawDllMain )
                DisableThreadLibraryCalls(hDllHandle);
#endif  /* defined (CRTDLL) */
        return TRUE ;
}

BOOL WINAPI _DllMainCRTStartup(
        HANDLE  hDllHandle,
        DWORD   dwReason,
        LPVOID  lpreserved
        )
{

// ...

      // invoke DllMain();

        if ( (dwReason == DLL_PROCESS_DETACH) ||
             (dwReason == DLL_THREAD_DETACH) )
        {
            if ( _CRT_INIT(hDllHandle, dwReason, lpreserved) == FALSE )
                retcode = FALSE ;
// ...

}

建议使用WinDBG附加到目标进程,跟踪一下就清楚了...


IP 地址: 已记录   报告
高端调试 » 软件调试 » WinDbg » Re: 使用umdh分析内存泄漏的疑惑,请张老师或其它大侠给予一些指点,什么感谢!

 
Legal Notice Privacy Statement Corporate Governance Corporate Governance
(C)2004-2020 ADVDBG.ORG All Rights Reserved.