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, @_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:

    @
    #include <QtGui/QApplication>
    #include <QCoreApplication>
    #include <QWidget>
    #include <QWebView>
    #include <QMainWindow>

    int main(int argc, char *argv[])
    {
    _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);

    QApplication a(argc, argv);

    #define LEAK

    #ifdef LEAK
    QWebView* pWidget=new QWebView();
    pWidget->setUrl(QUrl(QString("http://www1~")));
    #else
    QMainWindow* pWidget=new QMainWindow();
    #endif

    pWidget->show();

    bool r= QObject::connect (&a,
    SIGNAL(lastWindowClosed ()),
    pWidget,
    SLOT(deleteLater()));

    Q_ASSERT(r);

    return a.exec ( ) ;
    }

    @

    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 ?



  • 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:

    @
    QApplication app...
    QWebView* pWidget=new QWebView();
    pWidget->setUrl(QUrl(QString("http://www1~")));
    //...
    int ret_value = app.exec();
    delete pWidget;
    return ret_value;
    @

    I think you won't have a leak after that



  • [quote](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[/quote]
    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.


  • Moderators

    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.



  • [quote author="ixSci" date="1279373634"][quote](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[/quote]
    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.
    [/quote]
    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.
    [quote author="ixSci" date="1279373634"]
    Nevertheless, it doesn’t mean programmer should not clean after himself deliberately.
    [/quote]
    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.



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



  • Do you get a similar error, if you add an explicit @delete pWidget;@ in your code?



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



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



  • 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... :(



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



  • 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



  • [quote author="Benjamin Poulain" date="1294536526"]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.[/quote]

    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.



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


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.