【问题标题】:odd handle leak奇怪的手柄泄漏
【发布时间】:2011-08-10 01:32:03
【问题描述】:

我的应用程序(基本应用程序是 MFC 与 C++/CLI 互操作,但它也包含很多 C#、Windows 窗体、WPF)有句柄泄漏。应用程序启动后不久,我可以看到任务管理器中的句柄计数持续增长(以每秒 10 个新句柄的速度)。所以我用handles.exe 来看看它们是什么类型的句柄。我发现泄漏的句柄是进程句柄。它们是我的应用程序进程的进程句柄。

所以我想知道哪些操作通常会为其运行的进程创建句柄。知道吗?你见过这样的事情吗?考虑到我不能使用调试 DLL 并且我只能使用可以 xcopy 部署的工具,我还能做些什么来追踪泄漏。

更新:

我能够向它抛出 windbg!handle, !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

现在这告诉我什么?

【问题讨论】:

  • 它会继续增长吗? IE。这真的是泄漏还是只是运行时启动?
  • 它继续增长到数百万句柄,直到最终崩溃。
  • 托管代码调用栈呢?尝试使用 !clrstack(在 SOS 调试器扩展中可用)并查看它们是否为您提供有关此处正在创建这些句柄的线索。编辑:我不知道您是否能够直接从句柄获取托管调用堆栈,但您仍然可以在 kernel32!CreateThread 或 kernel32!CreateProcessEx 函数中放置例如断点并从那里获取托管堆栈
  • @bitbonk:你试过在OpenProcess设置断点吗?它会被击中吗?
  • 当应用程序最终崩溃时,您是否有异常处理程序或事件日志中的消息?这可能会给你更多的信息

标签: c# .net mfc interop handle-leak


【解决方案1】:

调用堆栈看起来不对。您是否正确设置了符号服务器? .symfix 应该在 Windbg 中发挥作用。之后你应该得到一个更好的堆栈跟踪。

看起来存在此问题的部分代码已被托管,因此中断 DuplicateHandle 和 OpenProcess 并将托管调用堆栈转储到那里是有意义的。这两种方法是唯一可以产生真实进程句柄的方法。

你可以像这样声明一个断点并在断点被命中时执行命令。 在这种情况下,打印托管堆栈,然后继续执行。

bp kernel32!OpenProcess "!ClrStack;g"

【讨论】:

  • 方法后面的数字很高。没有方法长于几百字节。如果您看到数以千计或更多的偏移量,则肯定表明您有错误或缺少符号。调试器使用作为回退然后模块的最近导出方法来显示至少一些东西。
【解决方案2】:

通过互操作调用 COM 对象的 Web 服务也有同样的问题。

我通过针对我创建的互操作对象显式调用 Marshal.ReleaseComObject 解决了这个问题。在那一刻之后对我来说没有问题。

希望对你有帮助。

【讨论】:

    【解决方案3】:

    那么...您是否明确地进行了性能计数器(如果是,请尝试禁用它们以缩小泄漏源的范围)。

    【讨论】:

      猜你喜欢
      • 2011-09-08
      • 2012-07-06
      • 1970-01-01
      • 1970-01-01
      • 2015-05-09
      • 2015-04-16
      • 2021-03-28
      • 2020-12-19
      相关资源
      最近更新 更多