如何克服Delphi10.3.3中访问TWebBrowser.Document时的内存泄漏

如何克服Delphi10.3.3中访问TWebBrowser.Document时的内存泄漏,delphi,memory-leaks,delphi-10.3-rio,twebbrowser,Delphi,Memory Leaks,Delphi 10.3 Rio,Twebbrowser,我使用StackOverflow()中的代码从网页获取完整响应: 函数TMain.GetWebBrowserHTML(常量WebBrowser:TwebbBrowser):字符串; 变量 一流:三流; 溪流:峡流; LPersistStreamInit:IPersistStreamInit; 开始 如果未分配(WebBrowser.Document),则 出口 LStream:=TStringStream.Create(“”); 尝试 LPersistStreamInit:=WebBrowser

我使用StackOverflow()中的代码从网页获取完整响应:

函数TMain.GetWebBrowserHTML(常量WebBrowser:TwebbBrowser):字符串;
变量
一流:三流;
溪流:峡流;
LPersistStreamInit:IPersistStreamInit;
开始
如果未分配(WebBrowser.Document),则
出口
LStream:=TStringStream.Create(“”);
尝试
LPersistStreamInit:=WebBrowser.Document as
IPersistStreamInit;
Stream:=TStreamAdapter.Create(LStream,sorreference);
LPersistStreamInit.Save(流,True);
结果:=LStream.DataString;
最后
LStream.Free();
结束;
结束;
在用一些大网页调用了几百次例程之后,我的内存不足了

显然,组件的
Document
属性存在已知问题,但将
WebBrowser.Document
替换为
WebBrowser.DefaultInterface.Document
的建议没有帮助。我真的不想尝试修复VCL,如果我知道在哪里以及如何修复,那么调用
Release
的另一个建议可能会奏效。而泄漏可能完全是另一回事。这个代码高于我的工资等级

我不能使用
TIdHTTP
,因为必须执行一些脚本,而且我仍然需要可视化脚本

另见:

显然,组件的文档属性存在已知问题

任何人看到这一点,请参考:

更新:据报道,该问题在10.0西雅图版本中已得到修复,因此不应出现 在10.3中不再发生

我真的不想尝试修复VCL,如果我知道在哪里以及如何修复,那么调用
Release
的另一个建议可能会奏效

你可以这样称呼它:

函数TMain.GetWebBrowserHTML(常量WebBrowser:TwebbBrowser):字符串;
变量
Disp:IDispatch;
一流:三流;
溪流:峡流;
LPersistStreamInit:IPersistStreamInit;
开始
Disp:=WebBrowser.Document;
如果未分配(Disp),则
出口
尝试
LStream:=TStringStream.Create(“”);
尝试
LPersistStreamInit:=显示为IPersistStreamInit;
Stream:=TStreamAdapter.Create(LStream,sorreference);
LPersistStreamInit.Save(流,True);
结果:=LStream.DataString;
最后
自由流;
结束;
最后
释放;
结束;
结束;
因此:

  • TWebBrowser.Document
    属性返回一个
    IDispatch
    ,由于
    TOleControl
  • 分配给
    Disp
    会增加refcount+1
  • LPersistStreamInit
    的cast+赋值将增加refcount+1
当函数退出时:

  • 显式的
    \u Release()
    减少refcount-1以解决该错误
  • LPersistStreamInit
    超出范围时,隐式的
    \u Release()
    将减少refcount-1
  • Disp
    超出范围时,隐式的
    \u Release()
    将减少refcount-1
  • 文档
    属性的返回值上的隐式
    \u Release()
    会使refcount-1递减
refcount已正确平衡

或者,您也可以这样做:

函数TMain.GetWebBrowserHTML(常量WebBrowser:TwebbBrowser):字符串;
变量
Disp:IDispatch;
一流:三流;
溪流:峡流;
LPersistStreamInit:IPersistStreamInit;
开始
指针(Disp):=WebBrowser.Document;
如果未分配(Disp),则
出口
LStream:=TStringStream.Create(“”);
尝试
LPersistStreamInit:=显示为IPersistStreamInit;
Stream:=TStreamAdapter.Create(LStream,sorreference);
LPersistStreamInit.Save(流,True);
结果:=LStream.DataString;
最后
自由流;
结束;
结束;
这样,您就不再需要显式的
\u Release()

  • TWebBrowser.Document
    属性仍然返回一个
    IDispatch
    ,该IDispatch的refcount错误地增加了+2,而不是+1
  • Disp
    的赋值不会增加refcount+1
  • LPersistStreamInit
    的cast+赋值将增加refcount+1
当函数退出时:

  • LPersistStreamInit
    超出范围时,隐式的
    \u Release()
    将减少refcount-1
  • Disp
    超出范围时,隐式的
    \u Release()
    将减少refcount-1
  • 文档
    属性的返回值上的隐式
    \u Release()
    会使refcount-1递减

参考计数正确平衡。

您知道泄漏的确切原因吗?如果是,是什么?如果没有,使用madExcept之类的工具,它会告诉您分配了什么以及在哪里,但没有释放。这可能有助于了解这些信息。有趣的是,多年来我与TWebBrowser合作过很多次,但从未意识到这一泄漏。“将
WebBrowser.Document
替换为
WebBrowser.DefaultInterface.Document
的建议没有帮助”-为什么没有帮助?@DelphiCoder
TStreamAdapter
实现了
IStream
接口,并被分配给
IStream
变量。因此,正常的接口引用计数将处理释放它的问题。@KevinDavidson您是否安装了10.3版的所有更新和修补程序,与此问题相关的,在10.3.3中以“固定”关闭。但我刚刚申请了原始版本,以防万一。@KevinDavidson您声称遇到的
TOleControl
问题实际上是在10.0西雅图解决的,所以您不应该在10.3中看到它,除非这是一个回归,或者是一个全新的泄漏。在10.4.1中检查,并添加了一个赋值