我们有一个.NET 2.0应用程序,它是一个服务,主要通过.NET远程连接多个客户端。在生产过程中,服务在客户端站点崩溃时出现 OutOfMemory异常,因此目前他们每天都被迫重启它,以避免意外崩溃。
以前,我已成功解决了托管代码中的几个内存泄漏案例(静态集合没有清理保存在其中的对象,另一个逻辑线程号不断增加)。所以我非常熟悉捕获内存转储并使用WinDbg + SOS搜索它们。
但是,在这种情况下,私有字节正在上升,而所有堆上的字节保持稳定,表示非托管代码内存泄漏。我收到了一个带有实际OOM异常的崩溃转储,这使得它更加明显:
检查Tess Ferandez关于处理.NET应用程序中非托管代码泄漏的博客,以及网络上的其他一些资源,我已经排除了许多动态程序集等常见问题 XmlSerializer 问题,或第三方原生DLL (没有)。但是,周围有很多 P / Invokes 。继续前进,检查堆如下:
第二个命令也返回了所有条目。现在,根据我读到的一些内容,我应该运行!heap -p -a来获取堆栈,但我得到的只是
根据this question,gflags使用不正确等等。但是,在本地启动服务并在其上附加调试器,目前不是一个选项。简而言之,我必须设置一个具有类似配置和负载的环境来完成它,而这还没有准备好。
所以,我很困惑。我不知道从哪里开始,或者即使我使用正确的方法解决该问题。任何指针都非常受欢迎。
在使用外部资源的线程上编辑#1: Thread.abort。具体来说,通过Oracle的ODP.NET提供程序进行数据库连接。这可能是本机堆泄漏的原因吗?
答案 0 :(得分:2)
然而,
周围有很多P / Invokes在使用外部资源的线程上编辑#1:Thread.abort
这只是遇到这种问题的完美风暴条件。它们中的任何一个如果足够自己导致不受控制的内存泄漏。看起来你的开发机器上的一切都很花哨。但是,它确实没有运用真机所处理的那种数据加载。
你不会从工具中获得很多帮助,而不是.NET类。绝对开始只是完全摆脱线程中止,这永远不会很好。你没有给出任何背景信息,因为你这么做很难给出具体的建议。绝对追求使用虚假的自动生成数据建立数据库,这样您就可以在舒适的隔间内检查代码调整的结果。您需要大量数据,因为它的泄漏速度不够快。
如果仍然遇到问题,则需要使用gflags.exe和umdh.exe等工具,这些工具可在Windows调试工具中找到。现在是SDK的一部分。最后,它们只适用于调试符号,Oracle并不是那种简单易用的公司。他们的生态系统是友好的移动 - 我会解决你的问题高薪顾问。如果你找到合适的,也可以解决这个问题。