之前我开发的服务程序疑似有内存漏洞。这种情况在本机调试不容易重现,在服务器上又不好调试,于是只好做内存转储然后用windbg来调试。
一般只需要执行几条指令就能找到造成内存漏洞的原因。
.loadby sos clr
加载.net插件
!dumpheap -stat -live
统计未能回收的对象数量和内存占用
-live 参数在微软的文档上没有,而又非常重要,用于排除掉那些可以进入垃圾回收队列的对象。上面那条指令还有其它参数,可以例如指定 -min 参数筛选较大的对象,-type 参数筛选特定名称的类型实例,-mt 参数指定特定对象等等。
输出结果有一个Free字段,表示内存页里的空洞,如果是这个值很大,而其它对象占用量正常,那就可能要考虑自己来做内存池管理内存。
点击上述指令的输出结果,可以查看统计对象的各个实例的地址。
还有一条重要的指令是
!gcroot 对象地址
可以查看是哪些对象引用了指定内存地址,导致内存释放不了。
一般这几条就够了。找到疑点后,可以在代码内植入跟踪变量,统计内存资源的申请和释放次数,确定哪些地方申请了资源但没有释放。如果还没找到异常点,那可能是非托管内存漏洞,这就比较麻烦了。
我在编写VS的Codist插件的时候发现,VS占用的内存不断增加,也是用上面的几条指令排除了插件占用的内存。但我最后还是投降了。因为VS本身也有内存漏洞,这个漏洞可能是在Roslyn里,会导致视图、解决方案、项目、文档和符号占用的内存无法正常释放。微软没给我支付工资,我也不管它的问题了。
如果可以直接在本机调试,而不是跟踪服务器上的内存漏洞,使用本机调试工具会更加方便,例如 Visual Studio 的性能分析组件。通过比较运行前后一段时间的对象数量,可以判定哪些资源在占用越来越多的内容。
【 在 feed 的大作中提到: 】
: rt大家有什么经验吗?比如有什么工具或者技术?谢谢谢谢! ...
--
修改:wmjordan FROM 223.104.69.*
FROM 223.104.69.*