您的位置:首页 > 其它

Webbrowser内存泄漏解决方案(修改OleCtrls.pas)

2014-07-25 07:50 218 查看
根据对IE、Maxtron、TT、世界之窗等浏览器的观察,可以肯定目前在所有的语言中如果调用Webbrowser这个ActiveX组件普遍存在内存泄漏问题。Delphi使用Webbrowser引起内存泄漏的原因是在OleCtrls.pas单元GetIDispatchProp和GetIntegerProp函数于对COM对象引用计数的错误处理上。

参见OleCtrls.pas源代码:



1

function TOleControl.GetIDispatchProp(Index: Integer): IDispatch;

2

var

3

Temp: TVarData;

4

begin

5

GetProperty(Index, Temp);

6

Result := IDispatch(Temp.VDispatch); //错误,COM对象赋值操作会增加对象的引用计数

7

end;

8


9

function TOleControl.GetIUnknownProp(Index: Integer): IUnknown;

10

var

11

Temp: TVarData;

12

begin

13

GetProperty(Index, Temp);

14

Result := IUnknown(Temp.VUnknown); //错误,COM对象赋值操作会增加对象的引用计数

15

end;

由于该错误代码会影响到所有继承TOleControl的组件,使其内存泄漏,所以我建议修改TOleControl的代码并重新编译OleCtrls.pas单元。该成如下的样子,即可解决问题。



1

function TOleControl.GetIDispatchProp(Index: Integer): IDispatch;

2

var

3

Temp: TVarData;

4

begin

5

GetProperty(Index, Temp);

6

//Result := IDispatch(Temp.VDispatch);

7

Pointer(Result) := Temp.VDispatch; //强制转换成Pointer再赋值就不会增加引用计数了

8

end;

9


10

function TOleControl.GetIUnknownProp(Index: Integer): IUnknown;

11

var

12

Temp: TVarData;

13

begin

14

GetProperty(Index, Temp);

15

//Result := IUnknown(Temp.VUnknown);

16

Pointer(Result) := Temp.VUnknown; //强制转换成Pointer再赋值就不会增加引用计数了

17

end;

18


19


问题分析:

该问题由来已久,自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如何被动的修复此漏洞。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: