Webbrowser内存泄漏解决方案(修改OleCtrls.pas)
根据对IE、Maxtron、TT、世界之窗等浏览器的观察,可以肯定目前在所有的语言中如果调用Webbrowser这个ActiveX组件普遍存在内存泄漏问题。Delphi使用Webbrowser引起内存泄漏的原因是在OleCtrls.pas单元GetIDispatchProp和GetIntegerProp函数于对COM对象引用计数的错误处理上。
参见OleCtrls.pas源代码:
由于该错误代码会影响到所有继承TOleControl的组件,使其内存泄漏,所以我建议修改TOleControl的代码并重新编译OleCtrls.pas单元。该成如下的样子,即可解决问题。
问题分析:
该问题由来已久,自Delphi6(我用的第一个Delphi版本,之前版本是否存在不确定)到Delphi2009,OleControl.pas始终存在该问题。修改之后可以解决内存泄漏问题,但Borland为何迟迟不进行更正呢?该内存泄漏对于一个需要频繁创建、操作和释放Ole对象的程序来说,是致命的。例如Doc:=Browser.Document as IHTMLDocument2这个语句就会引发GetDispachProp的执行,由于引用计数被错误的增加,对象不被使用时引用计数仍为1,所以该对象(Doc)不会被释放,进而引发内存泄漏。
由于Borland迟迟未能修复此问题,一些第三方组件例如:TEmbeddedWB,被动的去掉用_Release方法额外减少引用计数,已达到引用计数的平衡,我不太喜欢这样的做法,因为一旦该Bug被Borland或用户自行修复(我就自行修改了OleControl.pas),_Release将会导致引用计数向另一个更危险的方向偏移,Ole对象仍被使用的时候,引用计数已经归零,于是Ole对象被释放,接着是一个AV错误(Access violation错误)被引发。
下篇文章会详细介绍TEmbeddedWB如何被动的修复此漏洞。