简体   繁体   中英

Delphi TWebBrowser Memory Leak

My application uses a TWebBrowser that loads a webpage. The problem is, after closing the form containing the TWebBrowser, the memory used is not freed. If I open and close the form, the memory just keeps on increasing.

Saw some post regarding calling SetProcessWorkingSetSize() or CoFreeUnusedLibrariesEx() to solve this issue, but I'm not sure if any of these are the correct solution.

Any idea how to free the memory used by TWebBrowser?

QC#106829 describes one possible cause of memory leaks with TWebBrowser. Accessing Document (and any other properties that are implemented via TOleControl.GetIDispatchProp or TOleControl.GetIUnknownProp ) causes leaks because it calls AddRef without ever calling Release. As a workaround, you can manually call Release, or you can patch the VCL ( see here ), or you can avoid the problematic properties (for example, by using browser.DefaultInterface.Document instead of browser.Document ).

Using TWebBrowser does a lot of work behind the scenes, much of the same work a full instance of Internet Explorer would do. It is hidden from you, but still it's there and chances are it's unaccessible for us to force removing from memory. Check the memory usage before and between page loads, and test what happens when you call Navigate('about:blank'); . Also check whether your destructor gets called properly, and consider calling Navigate('about:blank'); from OnClose or OnCloseQuery. I found this does help the memory-situation a little bit.

The best solution is STOP using TWebbrowser.

CEF4Delphi is a free library that uses Chrome instead of Internet Explorer. Always up to date and very efficient :

https://github.com/salvadordf/CEF4Delphi

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}

To clear the memory, I use this function, found somewhere on the forums. It clears the "Working Set" much better than the SetProcessWorkingSetSize () method, but it is more difficult to call and it is registered in the Winapi.PsAPI unit. But, I noticed that both of these functions clean the "Working Set". And if you look at the "Allocated memory" column in the Task Manager, you can see that this parameter is not cleared. The "working set" of my application after cleaning can be reduced to 10 MB, but the all allocated memory will remain equal to 1.5 GB. And, in my opinion, this is what causes the error "Out of memory". And this error still appears if you look at heavy websites for a long time.

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

(WebBrowser.Document as IPersistStreamInit).InitNew;
procedure TForm1.FreeMemory;
begin
    if Win32Platform = VER_PLATFORM_WIN32_NT then
    SetProcessWorkingSetSize(GetCurrentProcess, $FFFFFFFF, $FFFFFFFF);
end;

and call it from time to time

FreeMemory;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM