做完近视手术注意什么:Webbroswer内存

来源:百度文库 编辑:偶看新闻 时间:2024/05/05 16:52:27
目前有2种方法,把窗体最小化的时候 内存就降下去了 
目前有2种方法,把窗体最小化的时候 内存就降下去了  set WindowState = 1WindowState 0是正常 1是最小化 2是最大化第二种,再做一exe程序,让主程序来调用 调用完毕就关闭(比较费劲了)

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

参见OleCtrls.pas源代码: 

 

Code
 1function TOleControl.GetIDispatchProp(Index: Integer): IDispatch;
 2var
 3  Temp: TVarData;
 4begin
 5  GetProperty(Index, Temp);
 6  Result := IDispatch(Temp.VDispatch);  //错误,COM对象赋值操作会增加对象的引用计数
 7end;
 8
 9function TOleControl.GetIUnknownProp(Index: Integer): IUnknown;
10var
11  Temp: TVarData;
12begin
13  GetProperty(Index, Temp);
14  Result := IUnknown(Temp.VUnknown);   //错误,COM对象赋值操作会增加对象的引用计数
15end;

 

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

Code
 1function TOleControl.GetIDispatchProp(Index: Integer): IDispatch;
 2var
 3  Temp: TVarData;
 4begin
 5  GetProperty(Index, Temp);
 6  //Result := IDispatch(Temp.VDispatch);
 7  Pointer(Result) := Temp.VDispatch;  //强制转换成Pointer再赋值就不会增加引用计数了
 8end;
 9
10function TOleControl.GetIUnknownProp(Index: Integer): IUnknown;
11var
12  Temp: TVarData;
13begin
14  GetProperty(Index, Temp);
15  //Result := IUnknown(Temp.VUnknown);
16  Pointer(Result) := Temp.VUnknown;  //强制转换成Pointer再赋值就不会增加引用计数了
17end;
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如何被动的修复此漏洞。