如何克服Delphi10.3.3中访问TWebBrowser.Document时的内存泄漏
我使用StackOverflow()中的代码从网页获取完整响应:如何克服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
函数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
- 分配给
会增加refcount+1Disp
- 对
的cast+赋值将增加refcount+1LPersistStreamInit
- 显式的
减少refcount-1以解决该错误\u Release()
- 当
超出范围时,隐式的LPersistStreamInit
将减少refcount-1\u Release()
- 当
超出范围时,隐式的Disp
将减少refcount-1\u Release()
属性的返回值上的隐式文档
会使refcount-1递减\u 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;
最后
自由流;
结束;
结束;
这样,您就不再需要显式的\u Release()
:
属性仍然返回一个TWebBrowser.Document
,该IDispatch的refcount错误地增加了+2,而不是+1IDispatch
- 对
的赋值不会增加refcount+1Disp
- 对
的cast+赋值将增加refcount+1LPersistStreamInit
- 当
超出范围时,隐式的LPersistStreamInit
将减少refcount-1\u Release()
- 当
超出范围时,隐式的Disp
将减少refcount-1\u Release()
属性的返回值上的隐式文档
会使refcount-1递减\u Release()
参考计数正确平衡。您知道泄漏的确切原因吗?如果是,是什么?如果没有,使用madExcept之类的工具,它会告诉您分配了什么以及在哪里,但没有释放。这可能有助于了解这些信息。有趣的是,多年来我与TWebBrowser合作过很多次,但从未意识到这一泄漏。“将
WebBrowser.Document
替换为WebBrowser.DefaultInterface.Document
的建议没有帮助”-为什么没有帮助?@DelphiCoderTStreamAdapter
实现了IStream
接口,并被分配给IStream
变量。因此,正常的接口引用计数将处理释放它的问题。@KevinDavidson您是否安装了10.3版的所有更新和修补程序,与此问题相关的,在10.3.3中以“固定”关闭。但我刚刚申请了原始版本,以防万一。@KevinDavidson您声称遇到的TOleControl
问题实际上是在10.0西雅图解决的,所以您不应该在10.3中看到它,除非这是一个回归,或者是一个全新的泄漏。在10.4.1中检查,并添加了一个赋值