vb.net虚拟内存 visual studio调整虚拟内存( 十 )


如果你怀疑有些对象在应该被释放后仍逗留在内存中,那需要做的第一件事就是找出这些对象都是什么 。
这看起来很明显,但是找起来却不是这样 。
建议通过内存工具找到非预期逗留在内存中的高级别对象或是根容器 。在项目x中,这些对象可能是类似LayoutView实例一样的对象们(我们使用了MVP(Model View Presentation )模式) 。在你的实际项目中,它可能依赖于你的根对象是什么 。
下一步就是找出它们该消失却还在的原因 。这才是调试器与工具能真正帮忙的 。它们可以显示出这些对象是如何链接在一起的 。通过查看那些指向“僵尸对象”(the zombie object)的引用你就可以找到引起问题的根本原因了 。
你可以选择 ninja方式(译者:间谍方式?)(参照 工具介绍章节中有关 SOS.dll 和 WinDbg 的部分) 。
我在项目X中用了JetBrains的dotTrace,本文中我将继续使用它来介绍 。在后面的工具相关章节中我会向你更多的介绍该工具 。
你的目标是找到最终引起问题的那个引用 。不要停留在你找到的第一个目标上 , 但是也要问问自己为什么这个家伙还在内存中 。
常见内存泄露的原因
上面提到的泄露情况在.net中较常见 。好消息是造成这些泄露的原因并不多 。这意味着当你尝试解决一个泄露问题时 , 不需要在大量可能的原因间搜寻 。
我们来回顾一下这些常见的罪魁祸首,我把它们区别开来:
·静态引用
·未注销的事件绑定
·未注销的静态事件绑定
·未调用Dispose方法
·Dispose方法未正常完成
除了上列典型的原因外,还有些其它情况也可能引发泄露:
·Windows Forms:绑定源滥用
·CAB:未移除对工作项的调用
我只列出了可能在你应用程序中出现的一些原因,但应该清楚你的应用程序依赖的其它.net代码、库实际使用中也可能引发泄露 。
我们来举个例子 。在项目x中,使用了一套第三方控件来构造界面 。其中一个用来显示所有工具栏的控件,它管理着一个工具栏列表 。这种方式没什么,但有一点,即使被管理的工具栏自身实现了IDisposable接口,管理类却永远也不会去调用它的Dispose方法 。这是一个bug.幸运的是这发生在一个很容易发现的工作区:只能我们自身来调用所有工具样的Dispose方法了 。不幸的是这还不够,工具栏类自身问题也不少:它并没有释放自身承载的控件(按钮,标签等等) 。所以在解决方案中还要添加对每个工具栏中控件的释放,但是这次可就没那么简单了,因为工具栏中的每个子控件都不同 。不管怎么样这只是一个特殊的例子,我要表达的观点是你应用程序中使用的任何第三方库、组件都可能引发泄漏 。
最后,还有一种由.net framework造成的泄露 , 由一些不好的使用习惯引起 。即使.net framework自身可能引发泄露,但这是你极少会遭遇到的情况 。把责任推到.net身上很容易 , 但在我们把问题推到别人头上前,还是应该先从自身写的代码出发,看看里面有没有问题 。
常见泄露演示
我已经列举出了泄露主要的来源,但我还不想仅限于此 。如果每个泄露我都能举个鲜活的例子的话,我想本文会更实用些 。好,我们先启动Vs 和 dotTrace  ,  然后看些示例代码 。我会同时演示如何解决或是避免每个泄露情况 。
项目X中使用了CAB和MVP模式,这意味着界面由工作空间、视图和呈现者组成 。简单起见,我决定使用包含一组窗口的Winform应用 。其中使用了与Jossef Goldberg的一篇关于“Wpf应用程序内存泄露”文章中相同的方法 。甚至我会直接把相同的例子和事件处理函数应用到我的Winform App中 。

推荐阅读