我的应用程序(基本应用程序是MFC与c++/CLI互操作,但它也包含很多c#, Windows窗体,WPF)有一个处理泄漏。在应用程序启动后不久,我可以看到任务管理器中的句柄数持续增长(以每秒10个新句柄的速度增长)。所以我使用handles.exe来查看它们是什么类型的句柄。我发现泄漏的句柄是进程句柄。它们是应用程序进程的句柄。
所以我想知道什么操作通常会创建它运行的进程的句柄。任何想法?你见过这样的东西吗?考虑到我不能使用调试dll,而且我只能使用可以xcopy部署的工具,我还能做些什么来跟踪泄漏呢?
更新:
我可以扔 winddbg 和!htrace查看它,发现所有进程句柄都是使用以下堆栈跟踪(按频率排序)创建的:
0x79f7570b: mscorwks!CorExitProcess+0x00022055
0x79f03edd: mscorwks!GetPrivateContextsPerfCounters+0x0000b6fe
0x79f04b87: mscorwks!GetPrivateContextsPerfCounters+0x0000c3a8
0x79f04b03: mscorwks!GetPrivateContextsPerfCounters+0x0000c324
0x79f919bf: mscorwks!CorExitProcess+0x0003e309
0x79f91b28: mscorwks!CorExitProcess+0x0003e472
0x792d6b4c: mscorlib_ni+0x00216b4c
0x1391a663: +0x1391a663
0x1391a0b1: +0x1391a0b1
0x7a9ea544: System_ni+0x005aa544
0x792a842f: mscorlib_ni+0x001e842f
或
0x7c8106f5: kernel32!CreateThread+0x0000001e
0x79f04bb2: mscorwks!GetPrivateContextsPerfCounters+0x0000c3d3
0x79f04b03: mscorwks!GetPrivateContextsPerfCounters+0x0000c324
0x79f919bf: mscorwks!CorExitProcess+0x0003e309
0x79f91b28: mscorwks!CorExitProcess+0x0003e472
0x792d6b4c: mscorlib_ni+0x00216b4c
0x1391a663: +0x1391a663
0x1391a0b1: +0x1391a0b1
0x7a9ea544: System_ni+0x005aa544
0x792a842f: mscorlib_ni+0x001e842f
或
0x08ec2eba: +0x08ec2eba
0x792b8277: mscorlib_ni+0x001f8277
0x792b8190: mscorlib_ni+0x001f8190
0x792b8040: mscorlib_ni+0x001f8040
0x792b7ff2: mscorlib_ni+0x001f7ff2
0x677e48f3: System_Runtime_Remoting_ni+0x000748f3
0x677e44be: System_Runtime_Remoting_ni+0x000744be
0x677e46ec: System_Runtime_Remoting_ni+0x000746ec
0x677e8408: System_Runtime_Remoting_ni+0x00078408
0x7926eb8d: mscorlib_ni+0x001aeb8d
这告诉我什么?
调用栈看起来不对。符号服务器设置正确了吗?.symfix在Windbg中应该可以做到这一点。之后,您应该得到一个更好的堆栈跟踪。
看起来有这个问题的部分代码是管理的,所以在DuplicateHandle和OpenProcess上中断并在那里转储托管调用堆栈是有意义的。这两个方法是唯一可以产生一个真正的进程句柄的方法。
您可以像这样声明一个断点,并在遇到断点时执行命令。在这种情况下,托管堆栈被打印出来,然后继续执行。
bp kernel32!OpenProcess "!ClrStack;g"
对于通过互操作调用COM对象的webservice有相同的问题。
我通过显式调用Marshal解决了这个问题。ReleaseComObject对我创建的互操作对象。在那一刻之后,我没有任何问题。
希望能有所帮助。
所以…您是否显式地使用性能计数器(如果是,请尝试禁用它们以缩小泄漏的来源)。