问题:
有没有一种简单的方法来获取运行应用程序中泄漏资源的类型列表?也就是说,通过连接到应用程序?
我知道Memproof可以做到这一点,但它会使应用程序变得如此缓慢,以至于应用程序甚至连续运行一分钟都难以实现。大多数任务管理器类似的工具可以显示数量,但不显示类型。
检查本身造成的影响很严重(停止应用程序进程)并不是问题,因为如果我接近极限,我可以使用任务管理器检查它(或者至少我希望如此)
欢迎提供有关资源泄漏狩猎(而不是内存)的任何其他见解。
背景:
我有一个Delphi 7/2006/2009应用程序(可编译所有三个版本),大约几周后,它开始表现出古怪的行为。但是,在它运行的其他几个系统中,它可以一直运行直到电源关闭。
我尝试加入一些调试代码来缩小问题范围。并发现异常是在文件保存时引发的EOutofResources(文件保存可能会发生数千次/天)。
我已经尝试推断出内存泄漏(使用FastMM),但由于数据流非常高(来自千兆位工业相机的60MB / s),我只能排除“缓慢”内存泄漏,而不能快速闪烁的内存泄漏在发生时耗尽内存。如果出现问题,应用程序将在不到半分钟的时间内填满内存。
主要嫌疑人是一些出错时留下的文件句柄和TMetafiles(它们被流式传输到这些文件中)。次要嫌疑人是VST、弹出菜单和Tframes。
更新:
另一个可能的提示:它在D7上运行了两年,并且现在问题出现在Turbo Explorer上(我用它来处理未转换为D2009的稳定项目)。
Paul-Jan:由于信息获取速度慢,每周仅发生一次(可能会在晚上发生),因此我需要结合一些内容来为星期四的到来做准备。简而言之,我不确定100%。我打算带上整个Systemtools集合,看看是否能找到一些东西(因为这样它就可以运行数天)。还有一种可能是我会看到一些打开的文件。(也许应该尝试找一些mingw lsof并调度它)
但是这个应用程序很少有GUI操作(它是一个机器视觉检查应用程序),除了屏幕刷新+/- 15/s,其中包括tbitmap stretchdraw + tmetafile,但是当我保存到磁盘时(TFileStream),我会遇到这个错误,句柄可能真的耗尽了。然而,在同一个流中,TMetafile也被保存到流中,后来的应用程序都没有了,它们可以运行数月。
------------------- 更新
我已经搜索了很多次,并设法在体外重现了两三次问题。当memusage约为256MB(系统有2GB),用户对象为200,gdi对象为500时,就会出现问题,没有比预期更多的文件打开)。这不是非常特殊的情况。我注意到我会泄漏一些句柄,可能是由于重新分配框架(VCL中的某些功能似乎会泄漏HPalette's)造成的,但我认为根本原因是不同的问题。我重复使用TMetafile,并在其中清除。我认为清除元文件并没有真正(总是?)调整资源大小,最终池中的每个元文件都达到了最大大小,并且具有20-40个以上的TMetafile(每个可以是几百KB),这将超过桌面堆限制。
这是一个理论,但我会尝试通过将客户的桌面限制设置为10MB来验证这一点,但在确认是否有任何变化之前需要数周时间。这个理论也证实了为什么这台机器很特别(可能这台机器自然地拥有稍大的平均元文件)。偶尔释放并重新创建池中的TMetafile也可能有所帮助。
幸运的是,这些问题(包括tmetafile和reparenting)在新一代应用程序中已经被设计出来了。由于特殊情况(以及我非常有限的测试窗口),这可能需要一段时间,但我决定暂时将桌面堆作为示例(尽管GDILeaks也有一定用处)。
审计还发现了线程中使用GDI类型(虽然只保存未被使用或连接的tmetafile到流中)。
------------- 更新2。
增加桌面限制似乎只稍微增加了发生问题的时间。
不幸的是,我无法进一步跟进此问题,因为机器已更新到不再有此问题的新版本框架。
总之,从旧框架到新框架,三个核心修改如下:
- 我不再通过重新定位框架来更改屏幕。我现在使用隐藏和显示表单。我改变了这个,因为我也偶尔会由于这个原因遇到非常罕见的崩溃或异常(可以通过点击解决)。但所有的崩溃都是在操作GUI时发生的,而不是像主要问题那样自发发生。 - 发生崩溃的程序例程涉及TMetafile。TMetafile已被设计出,并被一个更简单的自制格式所取代。(基本上是带有Opengl顶点的数组) - 绘图不再使用带有tmetafile叠加的tbitmap进行拉伸绘制,而是使用OpenGL。
当然,也可能是其他东西,在重写上述部分时发生了变化,修复了一些非常严重的详细错误。它必须是一个极其糟糕的错误,因为我尽可能地分析了上述系统。 更新于2012年11月 在私人邮件讨论后:回顾一下,下一步将是向metafiles对象添加计数器,并在每次x * 1000使用时重新实例化它们,看看是否会改变任何内容。如果您遇到类似的问题,请尝试查看是否可以定期销毁和重新初始化动态分配的长期资源。