Destruction of QObjects

后端 未结 2 930
北恋
北恋 2020-12-22 02:12

My program sometimes gives Segmentation Fault at the last statement in main function.

return a.exec();

I think problem is with order of destructio

相关标签:
2条回答
  • 2020-12-22 02:23

    So why does Documentation says that order of destruction doesn't matter?

    It means that you don't NEED to delete objects manually. Qt will register object within parent/child hierarchy and kill it when necessary.

    Of course, it can't track all pointers you might have stored somewhere. So if you take a pointer to object, then delete object's parent, then attempt to delete pointer you took, that'll be entirely your fault.

    Should we be always careful about deleting child object?

    No. When you delete child object it will unregister itself from its parent. If you delete second, then delete first, program will work fine. So you should remember that once you killed an object all its children are gone.

    By the way, Qt has QPointer class made specifically for this situation, so you should use it instead of raw pointers. QPointer will set itself to zero when object it points to is destroyed.

    But if I delete it causes segmentation fault.

    It means that your program has a bug you haven't fixed. And most likely (98% possibility) the bug is within your code, and is not Qt's fault. Debug the segfault and see where it happens.


    explanation

    QWidget* first = new QWidget;
    QWidget* second = new QWidget(first);
    delete first;
    delete second;
    

    When you delete first it also deletes second, because second is its child. However, your pointer second will not be automatically updated. It'll turn into dangling pointer (points at object that is no longer there), and attempt to delete it, will trigger undefined behavior, which, in your case, will crash the program.

    If you INSIST on keeping separate pointer for second AND deleting second after first (again), you can use something like this (don't forget to #include <QPointer>):

    QPointer<QWidget> first = new QWidget,
        second = new QWidget(first);
    delete first;
    delete second;
    

    However, there's no real need for that, and normally people simply do this:

    QWidget *first = new QWidget,
        *second = new QWidget(first);
    delete first;//second is deleted automatically
    

    Normally, in C++ you have to delete every object you allocated (with new) yourself, manually. This is error-prone, requires you to write a destructor, and you might somemetimes forget about it, which will result in memory leak. However, QObject automatically deletes all its children within its destructor, which means it is perfectly okay to do this:

     QObject *a = new QObject();
     QObject *b = new QObject(a);
     b = new QObject(a);
     b = new QObject(a);
    

    As long as you remember to delete top-level object, all its child resources will be automatically freed.

    However, Qt cannot track pointers you stored. So if you do something like this:

    QObject *a = new QObject(), *b = a;
    delete a;
    

    It will not update existing raw pointers. That's standard C++ behavior, by the way.

    That's what QPointers are for:

    QObject *a = new QObject(), *b = a;
    QPointer<QObject> c = a;
    delete a; 
    //at this point c is set to zero. a and b  still point at previous object locations.
    
    0 讨论(0)
  • 2020-12-22 02:32

    Qt can't control whether or not you attempt to delete an object that has already been destroyed. second was deleted when the first object was destroyed.

    However, the documentation does include the case when you delete a QObject using QObject::deleteLater(), which was designed for this case. I can't think of a case when you would delete a QWidget instead of using this method. The only time it wouldn't work is when you're outside the event loop, in which case you shouldn't be destroying/creating widgets anyway.

    0 讨论(0)
提交回复
热议问题