Kev*_*son 3 delphi memory-leaks twebbrowser delphi-10.3-rio
我正在使用 StackOverflow 中的此代码(如何从 TWebBrowser 获取 HTML 源代码)来获取网页的完整响应:
function TMain.GetWebBrowserHTML(const WebBrowser: TWebBrowser): String;
var
LStream: TStringStream;
Stream: IStream;
LPersistStreamInit: IPersistStreamInit;
begin
if not Assigned(WebBrowser.Document) then
Exit;
LStream := TStringStream.Create('');
try
LPersistStreamInit := WebBrowser.Document as
IPersistStreamInit;
Stream := TStreamAdapter.Create(LStream, soReference);
LPersistStreamInit.Save(Stream, True);
Result := LStream.DataString;
finally
LStream.Free();
end;
end;
Run Code Online (Sandbox Code Playgroud)
在使用一些大型网页对例程进行数百次调用后,我的内存不足。
显然,组件的Document属性存在一个已知问题,但替换为WebBrowser.Documentwith的建议WebBrowser.DefaultInterface.Document无济于事。我真的不想尝试修复 VCL,Release如果我知道在哪里以及如何做的话,另一个调用的建议可能会奏效。泄漏可能完全是另一回事。此代码高于我的工资等级。
TIdHTTP由于必须编写一些脚本,我无法使用,无论如何我都需要视觉效果。
显然组件的 Document 属性存在已知问题
供看到此内容的任何人参考:
RSP-32393:TOleControl.GetIDispatchProp 和 TOleControl.GetIUnknownProp 中的引用泄漏
更新:据报道此问题已在 10.0 Seattle 中修复,因此在 10.3 中不应再发生此问题。
我真的不想尝试修复 VCL,
Release如果我知道在哪里以及如何做的话,另一个调用的建议可能会奏效。
你会这样称呼它:
function TMain.GetWebBrowserHTML(const WebBrowser: TWebBrowser): String;
var
Disp: IDispatch;
LStream: TStringStream;
Stream: IStream;
LPersistStreamInit: IPersistStreamInit;
begin
Disp := WebBrowser.Document;
if not Assigned(Disp) then
Exit;
try
LStream := TStringStream.Create('');
try
LPersistStreamInit := Disp as IPersistStreamInit;
Stream := TStreamAdapter.Create(LStream, soReference);
LPersistStreamInit.Save(Stream, True);
Result := LStream.DataString;
finally
LStream.Free;
end;
finally
Disp._Release;
end;
end;
Run Code Online (Sandbox Code Playgroud)
因此:
TWebBrowser.Document属性返回一个IDispatchrefcount 由于错误而错误地增加了 +2 而不是 +1TOleControlDisp增加引用计数 +1LPersistStreamInit增加 refcount +1。当函数退出时:
_Release()减少引用计数 -1 以解决该错误_Release()时的隐式LPersistStreamInit递减引用计数 -1_Release()时的隐式Disp递减引用计数 -1_Release()对Document财产的返回值递减引用计数-1。引用计数正确平衡。
或者,您可以这样做:
function TMain.GetWebBrowserHTML(const WebBrowser: TWebBrowser): String;
var
Disp: IDispatch;
LStream: TStringStream;
Stream: IStream;
LPersistStreamInit: IPersistStreamInit;
begin
Pointer(Disp) := WebBrowser.Document;
if not Assigned(Disp) then
Exit;
LStream := TStringStream.Create('');
try
LPersistStreamInit := Disp as IPersistStreamInit;
Stream := TStreamAdapter.Create(LStream, soReference);
LPersistStreamInit.Save(Stream, True);
Result := LStream.DataString;
finally
LStream.Free;
end;
end;
Run Code Online (Sandbox Code Playgroud)
这样,您不再需要显式_Release():
TWebBrowser.Document属性仍然返回IDispatch其引用计数错误地增加了 +2 而不是 +1Disp不会增加引用计数 +1LPersistStreamInit增加 refcount +1。当函数退出时:
_Release()时的隐式LPersistStreamInit递减引用计数 -1_Release()时的隐式Disp递减引用计数 -1_Release()对Document财产的返回值递减引用计数-1。引用计数正确平衡。