应用程序泄漏字符串?
我的.NET应用程序确实有些沉重串装/操作和不幸内存消耗不断上升和上升,并在其与探查我看到很多未发行的字符串实例看时。现在,在某个时间点或另一个时间点,我确实需要所有对象都有这些字符串字段,但一旦完成,我就可以摆脱它的一半和我Dispose()并将实例设置为null,但垃圾收集器不会选择它..他们仍然在内存中(即使在处理后的半小时等)。应用程序泄漏字符串?
现在我怎么得到正确摆脱不需要的字符串/对象实例才能释放它们?
他们无处了(据我所知)提及,但如aspose的记忆分析器说他们到gc根的距离是'3'?
更新:原字符串从互操作实例来。是否有可能导致泄漏?
如..分配
myClass.StringProperty = interopInstance.Description.Text;
..没有我.StringProperty还是要那一个互操作的参考,因此“泄漏” /保持interopInstance未收&无法正常发布/取消封送的?
时仍然会使用含有该字段的类中的私有字段设置为null
可能是有用的。它将允许收集被引用的对象。但是,当该私有字段本身的实例未被引用时,它所引用的对象也是如此。换句话说,将对象上的私有字段置空即可,这将毫无用处。
我想你没有一个应用程序泄漏。也许你正在创建存储在大对象堆(LOH)中的字符串。对象在大于或等于85000字节(42492个字符或更多)时存储在LOH中。只有在完整的垃圾收集(第2代)发生时才收集LOH。因此,由于你似乎没有任何OutOfMemoryExceptions
,我不认为有泄漏。您的应用程序不会耗尽内存,并且GC不会收集Gen2。
您可以通过致电GC.Collect()
进行检查。这将删除所有未使用的大对象。
因此,虽然应用程序中可能没有泄漏,但内存占用可能不理想。特别是在编写桌面应用程序时,它不是唯一需要内存的应用程序。除此之外,大量内存也可能导致性能问题,因为GC必须更频繁地运行。
也许有可能以一种使用更少内存的方式重构代码。例如使用StringBuilder
对象(如果您还没有这样做)。或者甚至可能缓存池中的StringBuilder
对象,并重新使用它们而不是创建新对象。特别是在使用从池中获取的实例时设置Capacity属性。这可能特别有用,因为LOH易于分散,这可能会导致发生OutOfMemoryExceptions
。这在32位系统上只是一个问题,因为64位系统具有几乎无限的虚拟地址空间。 64bit在未来几年会越来越主流,我相信微软并没有投入资金来解决CLR的32位版本的这个问题,因此。
更新: 在互操作的情况下,字符串是序列化和反序列化。一个字符串作为字节数组发送,因此通常不会改变引用。但是,每次从interop获取一个字符串时,都会创建一个新的字节数组,并在.NET中将byte []复制到一个字符串中。这将使所使用的内存量增加一倍。
但是不要经常调用GC.Collect(),这对性能来说是相当糟糕的。 – 2010-05-11 10:30:46
@Rafal:当然可以。我不是说我应该在生产代码中使用它。用它来测试内存是否可收集。 – Steven 2010-05-11 10:34:05
哦,我确实得到了SystemOutOfMemoryExceptions ..在一个示例运行中,我拥有大约1200个我的类的实例,其中包括其他小字符串属性中的一个“大”字符......这意味着我的类的每个实例通常有几个100kbyte,有时几个兆字节的字符串'数据'在其中。 (我不幸需要)。 – 2010-05-11 10:37:58
只是在这个平台上,但你串联了很多字符串?如果是这样,你使用'+'运算符来做到这一点?一个字符串是不可变的,这意味着您可以在每次处理时在内存中创建一个新的字符串对象。
如果你串联字符串,你应该考虑使用一个StringBuilder对象(如果你还没有这样做)或者甚至是String.Concat()方法。这可能是问题,特别是如果你在任何一点连接循环中的字符串。
我一直致力于在许多终端之间传输数据的系统。这些终端生成文本数据(XML),然后压缩并传输到其他终端。最初,我们遇到了与使用越来越多Ram的应用程序完全相同的问题,并最终耗尽内存。连接到它的终端越多,其耗尽速度就越快。
该系统的性能不是最重要的功能,但长期正常运行时间。
用轮廓仪找出我们的记忆在哪里消失之后,我们发现我们的弦最后出现在LOH中,如果其中有任何实质性的话。
我知道这是有争议的,许多人说不要强迫GC.Collect,但我也发现其他网站,例如Rico Mariani,说如果你有特定的需求,你确定你的对象最终在蕙,然后继续前进做到这一点,只要记住GC.Collect会影响性能。
好消息是,一旦我们将此添加到程序的字符串处理区域中,我们就会继续关注应用程序整个生命周期中的相同的RAM使用情况,并且我们运行的一些系统具有正常运行时间> 60天。
我对Aspose的内存分析器不熟悉,但是如果它与GC的根有一定的距离,那么在我看来它被引用了。 Aspose不允许你看到它被引用的地方吗? – Steven 2010-05-11 11:27:19