4

I have an application that uses TWebbrowser to periodically navigate to a specific URL and extract some data. The app keeps runing 24x7 and does a lot of navigation in pages.

The problem is that TWebbrowser has a well-known memory leak problem, in which every time you navigate to a new page, the memory used for the application is increased. My app can easily use more than 2GB of RAM after some time. And after navigating hundred of times an 'Out of memory' or 'Out of system resources' exception is thrown and the only way to work around it is restarting the application.

The strange thing is FASTMM never shows these leaks. When I use my app for some minutes and close it, nothing is reported.

I've been searching for a solution for this problem for years (in fact since 2007 when I wrote the first version of my application). There are some workarounds but in fact, none of them solves the problem. For me the only workaround is really to close and open the app periodically.

I already tested the SetProcessWorkingSetSize approach, but it only shrinks the memory used by the app temporarily. After some seconds, the app uses a huge amount of memory again.

I also tried EmbeddedWB, but as it descends from TWebbrowser, it's plagued by the same issue.

By the way, I can't use a simple component like IdHTTP, because I need to do some JavaScript manipulation in the website visited.

Does anyone know if is there REALLY a solution for this problem?

TigerhawkT3
  • 48,464
  • 6
  • 60
  • 97
delphirules
  • 6,443
  • 17
  • 59
  • 108
  • 2
    You really should not be using a visual component for non-visual work. Find another solution. As for FastMM, it is not the one allocating the WebBrowser's internal memory, so it cannot track it. – Remy Lebeau Oct 24 '13 at 17:07
  • There are some leads to a solution, but it depends on your requirement. For instance, (1) can you close the browser every hour? (2) must it be a MSIE? BTW: "start a bounty" will be fair to answer such a question indeed. – stanleyxu2005 Mar 20 '14 at 18:47
  • Possible duplicate of http://stackoverflow.com/q/10224801/25507 – Josh Kelley Jul 30 '14 at 20:24

1 Answers1

7

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).

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Josh Kelley
  • 56,064
  • 19
  • 146
  • 246
  • I already did this fix and could reproduce the fix, but still the component keeps using more and more memory during time... – delphirules Sep 29 '14 at 19:10
  • 1
    @delphirules - The way I finally debugged my TWebBrowser memory leaks was to have a TTimer event that invoked the leaking code many times a second (so I could easily see whether or not a leak occurred), then repeatedly delete or comment out blocks of code and rerun, until I could zero in on which lines of code triggered the leak. Hope this helps. – Josh Kelley Sep 29 '14 at 19:20
  • 6
    @delphirules - This isn't a "send some example code" type of problem. If your leak is caused by QC#106829, then use `browser.DefaultInterface.Document` instead of `browser.Document`. If your leak is caused by something else, then identify the procedure or form in your code that causes the leak, use a TTimer event to invoke that several times a second (so the leak is really obvious), then start deleting or commenting out blocks of code in your procedure or form until you identify the particular statements that trigger the leak. – Josh Kelley Oct 20 '14 at 13:46
  • thank you, will try it. are you sure you could really solve the problem ? your app using TWebbrowser can navigate to hundred of pages and your app process is not consuming tons of ram ? – delphirules Oct 21 '14 at 16:42
  • 1
    @delphirules - Based on the testing we've been able to do, we're able to handle rapidly refreshing JavaScript-heavy pages without consuming tons of RAM. On the other hand, we only have a few specific pages and sites we need to handle, and your use of TWebBrowser may be different than ours. Regardless, I've seen enough comments from people using TWebBrowser and TEmbeddedWB that I'm certain it can be made to work. – Josh Kelley Oct 21 '14 at 16:58
  • My app is Facebook related; i can easily reproduce the memory leak by simply navigating to 'https://www.facebook.com'. Each time the app navigates to it, the memory usage is increased. After 10 times navigating, my app is consuming almost 500mb of ram : just navigating and doing anything more : / – delphirules Feb 05 '15 at 22:19
  • QualityCentral is dead. There is a related report in QualityPortal: [RSP-19473](https://quality.embarcadero.com/browse/RSP-19473). And I have just now filed a duplicate of QC#106829 into QualityPortal as well: [RSP-32393](https://quality.embarcadero.com/browse/RSP-32393) – Remy Lebeau Feb 10 '21 at 18:30
  • 1
    Turns out the `TOleControl.GetIDispatchProp/GetIUnknownProp()` bug was fixed in 10.0 Seattle. – Remy Lebeau Feb 10 '21 at 22:16
  • `TCppWebBrowser` doesn't have `DefaultInterface`, could you please supplement the answer with the same but for `DefaultDispatch` that `TCppWebBrowser` uses? I have also asked the same on - https://stackoverflow.com/questions/67671233/no-defaultinterface-in-tcppwebbrowser – Coder12345 May 24 '21 at 11:26
  • @Coder12345 - It's been several years since I looked into this, and I no longer work with C++Builder, but I think I decided that using TWebBrowser worked better than TCppWebBrowser (partly to have easier access to properties like this) and that TCppWebBrowser didn't really gain me anything. – Josh Kelley May 24 '21 at 18:43
  • @JoshKelley No worries, I've solved the problem in my question myself it is pretty simple - `DelphiInterface(browser->DefaultDispatch)->Document` or `DelphiInterface(browser->Application)->Document`. `TCppWebBrowser` does have a few more events than `TWebBrowser` though and is somewhat more compatible with the C++ workflow. The only reason I can think of, one might prefer `TWebBrowser` maybe cause more care put into it with the RAD-Studio devs. – Coder12345 May 25 '21 at 11:09