dinghao

记录成长点滴

 

Silverlight内存泄露(四)解决内存泄露

定位泄露内存的对象很容易,但是找出引起泄露的原因并不容易,因为从GC到目标对象(内存泄露对象)的路径不只一条,找出哪条路径引起了内存泄露是非常烦人的工作,大部分情况只能凭借自己的经验。

一般我们都不会关注内存问题,当内存成为问题的时候,程序可能都开发完成了,这时候对象图会引入第三方库、.net 框架、本公司的其他库,需要梳理GC到目标对象的所有路径,并测试每一条路径,确认哪条引起了内存泄露。在测试某条路径的时候,需要排除其他路径对内存泄露的影响,这时候排除其他路径影响非常难,会牵涉到很多代码的改动。

以一个例子说明如何解决内存泄露,强制GC后,对比两个快照,发现没有被回收的对象,如下图BookPageSearche不是当前页面(现在看着还头疼,内存问题真是一个可以让人发疯的问题):

3

这张图包含了Command、Event、Style、MEF引起的内存泄露,几乎包括所有我发现的内存泄露情况,这一篇讨论内存泄露的通用解决方案,不会针对每种问题讨论。

看标记出的几个点:

对目标来说,如果切断1,目标对象肯定会被释放,但是目标对象的直接父对象属于.net控件,不可能在这一点切断路径。

对于标记2,切断它会切断3、4、5,标记二NavigationCommand属于自己的代码可以在此释放内存,但并不应该在此释放。

标记3、5圈起来的部分,是由其他View内存引起的问题与这个目标对象关系不大,其他View(About、SIteNav)内存被释放后,这个路径自动被切断。

标记9是由自定义导航框架引起的内存泄露。

标记8是由MEF引起的内存泄露,并且是唯一与目标对象直接有关的路径(BookPageSearche),在这个目标中应从此点着手释放内存。

下面一张图是和上一张对照的,可对照看。显示了BookPageSearche是当前页面时的对象图,未执行GC。

3

需要避免的误区

第一直觉肯定是目标对象的直接父对象,只要他释放,不用再管更上层的诸多引用,如果这么处理可能属于头痛医头脚痛,不找点最合适的切断路径的点,会给程序修改带来灾难,后续会出现数不清的需要释放的对象。所以在释放内存是一定要避免不分析清楚直接下手释放。

总解

不知道有多少人能看的懂,这篇的目的只是提供一种通用的分析方法,分析出从GC到目标对象的多条路径应该选择哪几条路径释放内存,选择了合适路径以后又该在路径中的那个对象出断开引用。这其中的分析大部分只能凭借经验。

一些技巧

多看几个类似的对象图,比如找View的内存泄露,多看几个View,如About、Home等,从中找到共同点。

对于某个对象图,只解决直接和这个对象有关的内存泄露,而忽略由其他对象引起的内存问题。

从最简单的泄露问题着手,解决了一个泄露问题,会发现对象图会小很多,再分析其他泄露问题会简单一些。

posted on 2011-04-13 23:33  思无邪  阅读(1905)  评论(4编辑  收藏  举报

导航