July 13, 2010

florent.revelut florent.reve..
Lab Rat
103 posts

How to delete properly a QWebView ?

 

Hello,

I’ve been using Qt 4.6.2 for a while and I’m now stuck on an issue : I can’t use QWebView without being crowded by memory leaks.

Is there a wizard way to delete it ?

I created an application with QtCreator wizard, I tried compiling it with gcc (ubuntu 10.04 with qt 4.6.2) or visual 2008 (self compiled qt 4.6.2).

On linux, Valgrind detects a whole bunch of leaks (log available, code source as well).

On Windows,

  1. _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
shows a full list of non deallocated memory on termination.

I tried using this simple app as well:

  1. #include <QtGui/QApplication>
  2. #include <QCoreApplication>
  3. #include <QWidget>
  4. #include <QWebView>
  5. #include <QMainWindow>
  6.  
  7. int main(int argc, char *argv[])
  8. {
  9.    _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
  10.  
  11.   QApplication a(argc, argv);
  12.  
  13.  #define LEAK
  14.  
  15. #ifdef LEAK
  16.   QWebView*  pWidget=new QWebView();
  17.   pWidget->setUrl(QUrl(QString("http://www1~")));
  18. #else
  19.   QMainWindow* pWidget=new QMainWindow();
  20. #endif
  21.  
  22.  
  23.   pWidget->show();
  24.  
  25.   bool r= QObject::connect (&a,
  26.     SIGNAL(lastWindowClosed  ()),
  27.     pWidget,
  28.     SLOT(deleteLater()));
  29.  
  30.   Q_ASSERT(r);
  31.  
  32.   return a.exec ( ) ;
  33. }

Using delete / deleteLater / WA_deleteOnClose provides almost the same result… And using a breakpoint, I see that QWebView destructor is called…

Same leaks appear…. Any idea ?

13 replies

July 17, 2010

Zlatomir Zlatomir
Robot Herder
327 posts

Disclaimer: I’m not an expert in this, but i don’t like this way of doing things, if you allocate dynamically the MainWindow/Widget then delete it too (i might be wrong) but i don’t think that is “safe” to assume that the OS will reclaim the (dynamic allocated) memory immediately after your app is closed

So, if you use dynamic for mainWindow/Widget use this code:

  1.   QApplication app...
  2.   QWebView*  pWidget=new QWebView();
  3.   pWidget->setUrl(QUrl(QString("http://www1~")));
  4.   //...
  5.   int ret_value = app.exec();
  6.   delete pWidget;
  7.   return ret_value;

I think you won’t have a leak after that

July 17, 2010

ixSci ixSci
Lab Rat
203 posts

(i might be wrong) but i don’t think that is “safe” to assume that the OS will reclaim the (dynamic allocated) memory immediately after your app is closed

Windows frees all resources which process possesses when terminates it. I don’t actually know how it works in other OS, but I suppose that it works the same.

Nevertheless, it doesn’t mean programmer should not clean after himself deliberately.

July 17, 2010

Tobias Hunger Tobias Hunger
Mad Scientist
3224 posts

All sane OSes do clean up after the applications.

But memory leak scanners of course need to report issues like that: It can not know whether it is a actual leak or an informed decision made by the programmer to leave the cleanup to the OS (which you should not do!). So even though no memory is lost by quitting an application without deleting your objects due to the OS cleaning up this will get reported by all memory checking tools.

I am pretty convinced that the memory leak reported by Florent will go away when he actually deletes his pointer after use.

If you are considering to not delete your stuff please be reminded that this is very bad form and it can (and will if you are not extremely careful!) lead to corruption of data. So: Always delete your data structures.

July 18, 2010

Zlatomir Zlatomir
Robot Herder
327 posts

ixSci wrote:
(i might be wrong) but i don’t think that is “safe” to assume that the OS will reclaim the (dynamic allocated) memory immediately after your app is closed

Windows frees all resources which process possesses when terminates it. I don&#39;t actually know how it works in other OS, but I suppose that it works the same.

Yes the OS will eventually do the cleaning but not immediately when your app finishes (so there still is a leak at the end of that application) and i consider this a “bad” practice.
ixSci wrote:

Nevertheless, it doesn’t mean programmer should not clean after himself deliberately.

Correct, especially that in an bigger application the MainWindow/Widget(0) “should” trigger the deletion and proper destruction of everything else (the whole parent-child “chain”) so the programmer can allocate MainWindow on the stack of main function, or on the heap and delete it the way i showed in the my first post.

December 21, 2010

florent.revelut florent.reve..
Lab Rat
103 posts

Actually, the pointer IS deleted : if I put a breakpoint in QWebView destructor, it’s called, thus proving my point (and that’s what the ->deleteLater is for)
However a bunch of resources are still held : this might be easier, but it proves painful when tracking leaks made by our own programs. Especially when using webkit, we’re litterally flooded in reports (agreed they will be freed by OS at some point), thus preventing from detecting anything else. looking closer, I’ve seen leaks of a mutex array as well, I’ll try to point it more clearly soon.

December 21, 2010

Volker Volker
Robot Herder
5428 posts

Do you get a similar error, if you add an explicit

  1. delete pWidget;
in your code?

December 22, 2010

fcrochik fcrochik
Lab Rat
517 posts

deleteLater is handled by the event loop. I am not sure that the event loop will have a chance to process this after the last window is closed and before the application exits.

Regardless, you are writing c++ code and you should always use delete.
Qt has spoiled us with the parent deleting the children automatically but you should be very careful.

 Signature 

Certified Specialist & Qt Ambassador Maemo, Meego, Symbian, Playbook, RaspberryPi, Desktop… Qt everywhere!

December 22, 2010

florent.revelut florent.reve..
Lab Rat
103 posts

Actually calling the delete does not help.
Event loop has time to process it, as my breakpoint is stating.

Concerning delete vs deleteLater, it has nothing to do with cascaded destruction : when using multiple thread, you have to delete the objects in the correct thread (just think of deleting QNetworkReply).

As far as the event loop has time to process the event, using deleteLater and delete is exactly the same. In top example, I had the exact same behaviour by using an actual delete.
What is pushing my point is : undef the compilation option, you end up with a simple widget and no leak, it’s thus deleted, pushing the fact that leak actually occurs as part of the QWebView.

January 8, 2011

DavidGOrtega DavidGOrtega
Lab Rat
25 posts

Hi florent,

I’m with you… nobody seems to understand that the destructor is ACTUALLY CALLED using delete or deleteLater(), in fact using delete with threads instead of using SLOT connecting the finished signal will cause an ERROR.

The bug is in Webkit itself.

Also for me it’s a surprise how many Qt followers does not even know the workings inside deleteLater() ;)

I’m considering use V8… :(

January 9, 2011

Benjamin Poulain Benjamin Poulain
Lab Rat
153 posts

I might miss something but I do not see the log of the objects leaking you mentioned.

You should also use Qt 4.7. I do not know about a future release of Qt 4.6, so even if there is a leak in that version, it is unlikely to be fixed anytime soon.

Personally, I use Rekonq with the branch of Qt 4.7. It has been running for about two weeks, loading a few hundreds pages, and the memory usage is reasonable. So I guess if there is a leak there, it is a very small one.

Finally, note that you will not get all the memory back after deleting a QWebView and loading websites. This is simply because Qt does not free the memory allocated for fonts. There is no API to unload fonts.

January 9, 2011

Benjamin Poulain Benjamin Poulain
Lab Rat
153 posts

Hum, and I do not think it is the right place to discuss potential bugs.

You should collect as much data as you can, like finding which objects are leaking (valgrind’s massif is great for that). When you have those info, you report a bug on http://webkit.org/new-qtwebkit-bug

Note that some tools get really confused with the custom allocators and the JIT of JavascriptCore. If you can’t find which objects are leaking, there is likely a problem with your tool.

To see how to build WebKit trunk on different platforms, see http://trac.webkit.org/wiki/QtWebKit

January 11, 2011

DavidGOrtega DavidGOrtega
Lab Rat
25 posts
Benjamin Poulain wrote:
Finally, note that you will not get all the memory back after deleting a QWebView and loading websites. This is simply because Qt does not free the memory allocated for fonts. There is no API to unload fonts.

I have to see the source code to see what is definitely happening there but at first sight in term of c++ thats only a memory block that should be only deallocated ¿am I wrong?

In the other hand, is there any form to only allow one kind of default font?? embedded movies like flash has to be deallocated also manually???

In my case my server spends 1gb after less than 1500 petitions, a lot of memory indeed, anyway I’m compiling the Qt fancy browser example today to have some tests.

January 14, 2011

DavidGOrtega DavidGOrtega
Lab Rat
25 posts

Qt 4.7 has less memory leak than 4.5.3 but still is loosing a lot of memory!!

Since I know thats hard to believe I’m preparing a demo…

 
       Compiling qt64bit with webkit ››

You must log in to post a reply. Not a member yet? Register here!