Delphi TWebBrowser内存泄漏

Delphi TWebBrowser内存泄漏,delphi,delphi-2009,twebbrowser,Delphi,Delphi 2009,Twebbrowser,我的应用程序使用TWebBrowser加载网页。问题是,在关闭包含TWebBrowser的表单后,使用的内存没有被释放。如果我打开和关闭表单,内存就会不断增加 看到一些关于调用SetProcessWorkingSetSize()或cofreeunsedLibrarieSex()来解决此问题的帖子,但我不确定这些是否是正确的解决方案 知道如何释放TWebBrowser使用的内存吗 使用TWebBrowser在幕后做了大量工作,大部分工作与完整的Internet Explorer实例相同。它对你是隐

我的应用程序使用TWebBrowser加载网页。问题是,在关闭包含TWebBrowser的表单后,使用的内存没有被释放。如果我打开和关闭表单,内存就会不断增加

看到一些关于调用SetProcessWorkingSetSize()或cofreeunsedLibrarieSex()来解决此问题的帖子,但我不确定这些是否是正确的解决方案


知道如何释放TWebBrowser使用的内存吗

使用TWebBrowser在幕后做了大量工作,大部分工作与完整的Internet Explorer实例相同。它对你是隐藏的,但它仍然在那里,我们很可能无法从记忆中强行移除它。检查页面加载之前和加载之间的内存使用情况,并测试调用
Navigate('about:blank')时发生的情况。还检查析构函数是否被正确调用,并考虑调用<代码>导航(“关于:空白”);代码>来自OnClose或OnCloseQuery。我发现这确实有助于改善内存状况。

要释放内存,只需初始化新文档:

(WebBrowser.Document as IPersistStreamInit).InitNew;
并时不时地给它打电话

FreeMemory;
描述TWebBrowser内存泄漏的一个可能原因。访问
文档
(以及通过
TOleControl.GetIDispatchProp
TOleControl.GetIUnknownProp
实现的任何其他属性)会导致泄漏,因为它调用AddRef而从未调用Release。作为一种解决方法,您可以手动调用Release,或者修补VCL(),或者可以避免出现问题的属性(例如,使用
browser.DefaultInterface.Document
而不是
browser.Document

为了清除内存,我使用了这个功能,可以在论坛上找到。它清除“工作集”的效果比SetProcessWorkingSetSize()方法好得多,但调用起来更困难,并且它注册在Winapi.PsAPI单元中。
但是,我注意到这两个函数都会清理“工作集”。如果您查看任务管理器中的“已分配内存”列,可以看到此参数未被清除。清理后,我的应用程序的“工作集”可以减少到10 MB,但所有分配的内存将保持等于1.5 GB。在我看来,这就是导致错误“内存不足”的原因。如果你长时间浏览大量网站,这个错误仍然会出现。

最好的解决方案是停止使用TWebbrowser

CEF4Delphi是一个使用Chrome而不是Internet Explorer的免费图书馆。始终保持最新且非常高效:


我认为您可能错误地解释了您用来收集这些统计数据的任何内容。堆分配器非常复杂,在需要释放内存之前,它们通常会保留内存。如果系统有足够的可用内存,为什么要花时间将它返回操作系统,而你可以免费保留它。你是如何关闭(和打开)表单的,它是否被任何东西释放了?如果你在不加载网页的情况下打开和关闭表单,你是否仍然存在内存问题?你可能会发现这样一个泄漏应用程序的例子。即使以
TWebBrowser
作为组件的表单被释放,线程仍会保持运行,并且每个新实例都会创建新的线程(因此内存消耗会增加)。我还没有找到解决方案,我尝试了很多方法,包括
cofreeunsedlibrariesex
,导航到
about:blank
,没有任何帮助。这是一个严重的问题,因为创建多个表单实例需要耗费大量的系统资源。我的建议是隐藏表单,而不是发布,因为它在这里似乎没有效果;它只是“压缩”使用的内存,但在新导航后,以前使用的所有巨大内存都会重新定位。此解决方案不起作用,内存仍在不断增加。使用
browser.DefaultInterface.Document
而不是
browser.Document
解决了我的内存泄漏问题。感谢您在Delphi10.0中修复了这个
TOleControl
bug。
FreeMemory;
Uses Winapi.PsAPI;
 ...
{$IFDEF WIN32}
procedure TForm1.MemoryFree;
var
  HandleCaptureProcessus: THandle;
  UnProcessus: TProcessEntry32;
  PIDProcessus: THandle;
  HandleProcessus: THandle;
  NameOfProcess: string;
begin
  PIDProcessus := 4294967295;
  NameOfProcess := ExtractFileName(Application.ExeName);

  HandleCaptureProcessus := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  UnProcessus.dwSize := SizeOf(TProcessEntry32);

  Process32First(HandleCaptureProcessus, UnProcessus);
  repeat
    if UnProcessus.szExeFile = NameOfProcess then
    begin
      PIDProcessus := UnProcessus.th32ProcessID;
      Break;
    end;
  until not Process32Next(HandleCaptureProcessus, UnProcessus);

  if PIDProcessus = 4294967295 then
  begin
    CloseHandle(HandleCaptureProcessus);
    exit;
  end;

  HandleProcessus := OpenProcess(PROCESS_ALL_ACCESS, False, PIDProcessus);

  EmptyWorkingSet(HandleProcessus);

  CloseHandle(HandleProcessus);
end;
{$ELSE}
procedure TForm1.MemoryFree;
begin
  //**
end;
{$ENDIF}