Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Is qobject_cast a valid way to test destruction state?
QtWS25 Last Chance

Is qobject_cast a valid way to test destruction state?

Scheduled Pinned Locked Moved General and Desktop
5 Posts 3 Posters 3.1k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Offline
    D Offline
    DerManu
    wrote on last edited by
    #1

    Hi there,

    I've got a class deriving from QObject, so

    QObject -> QClass1

    and some other class

    QOtherClass

    Now in the QOtherClass destructor, it does stuff in an QClass1 instance. This is obviously okay, if QOtherClass is usually destructed manually before QClass1 destruction, which is the normal case. In some situations however, QOtherClass is direct child of a QObject, which leads to the situation that on program shutdown, the QOtherClass dtor is called (via QObject memory management) after the (also QObject-managed) QClass1 was torn down to the level of a QObject already. So calling QClass1 methods on that instance will cause segfaults.

    Currently, I check in the QOtherClass dtor:
    @
    QClass1 theClass1Instance;
    ...
    if (qobject_cast<QClass1
    >(theClass1Instance))
    theClass1Instance->doStuff();@

    Which seems to work, i.e. it lets me know whether theClass1Instance is already partly torn down.

    Is that a valid use case for qobject_cast, can I depend on it?

    1 Reply Last reply
    0
    • A Offline
      A Offline
      akonradwesolutions
      wrote on last edited by
      #2

      I'm pretty sure this doesn't work. You can use a QPointer to create a safe pointer to a QObject instance:

      @
      QPointer<QClass1> safe = new QClass1();
      // ...
      if (!safe.isNull()) {
      safe->doStuff();
      }
      @

      1 Reply Last reply
      0
      • D Offline
        D Offline
        DerManu
        wrote on last edited by
        #3

        [quote author="Arnold Konrad" date="1367781898"]I'm pretty sure this doesn't work.[/quote]
        Well the question really isn't if it works, because it actually does. The question is more whether it's intended and dependable behaviour for future versions to come.

        Anyone can test it with the following code:
        mainwindow.h:
        @
        #ifndef MAINWINDOW_H
        #define MAINWINDOW_H

        #include <QMainWindow>
        #include <QDebug>

        namespace Ui {
        class MainWindow;
        }

        class QClass1 : public QObject
        {
        Q_OBJECT
        public:
        QClass1(QObject *parent) : QObject(parent) {}
        void doStuff() { qDebug() << Q_FUNC_INFO; }
        };

        class QOtherClass : public QObject
        {
        Q_OBJECT
        public:
        QOtherClass(QClass1* parent) : QObject(parent), mClass1(parent) {}
        ~QOtherClass()
        {
        qDebug() << static_cast<bool>(qobject_cast<QClass1*>(mClass1));
        mClass1->doStuff();
        }

        private:
        QClass1 *mClass1;
        };

        class MainWindow : public QMainWindow
        {
        Q_OBJECT

        public:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();

        QClass1 *class1;
        QOtherClass *otherClass;

        private:
        Ui::MainWindow *ui;
        };

        #endif // MAINWINDOW_H

        @

        mainwindow.cpp:
        @
        #include "mainwindow.h"
        #include "ui_mainwindow.h"

        MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
        {
        ui->setupUi(this);

        class1 = new QClass1(this);
        otherClass = new QOtherClass(class1);
        }

        MainWindow::~MainWindow()
        {
        delete otherClass;
        delete ui;
        }
        @

        Now comment out the "delete otherClass" in ~MainWindow and you'll see the debug output of ~QOtherClass changes from true to false – because then QObject-memory-management deletes otherClass after QClass1 has been torn down. While when you delete otherClass in ~MainWindow, the QClass1 still exists and the qobject_cast test returns true.

        --

        I'm aware of smart pointers but I'd like to avoid them in this special case, thanks for bringing it up nevertheless.

        1 Reply Last reply
        0
        • JKSHJ Offline
          JKSHJ Offline
          JKSH
          Moderators
          wrote on last edited by
          #4

          I suspect that it will do what you want for a long time because the implementation of qobject_cast is unlikely to change within the lifetime of Qt 5, but it's probably just a happy coincidence. qobject_cast wasn't designed to be a deletion detector; it was designed to do be a dynamic_cast for QObjects that doesn't require RTTI, and it just happens to report a failure if the object has already been deleted (at least in the cases that you've tried).

          You're entering undefined territory, so tread carefully :)

          P.S. Other people have "used this trick too":http://www.gamedev.net/topic/262517-dynamic_cast-not-failing-on-bad-pointers/#entry2604314 with dynamic_cast, but the consensus seems to be "don't do it"

          Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

          1 Reply Last reply
          0
          • D Offline
            D Offline
            DerManu
            wrote on last edited by
            #5

            Well it's not really a test whether QObject has been deleted (like QPointer<QObject> would), right? The moment I'm interested in is in the teardown process where QObject still exists but the part of the instance that is defined by the subclass isn't. That's why I had hoped qobject_cast would be safe there, since the QObject is fine at that time.

            Well I guess I'll have to manually delete all the QObject children of QClass1 in its dtor. Not the cleanest method since that's duplicating code of the QObject dtor, but there seems to be no nice way to handle it.

            Thanks for your suggestions (further ideas always welcome, of course ;)

            1 Reply Last reply
            0

            • Login

            • Login or register to search.
            • First post
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • Users
            • Groups
            • Search
            • Get Qt Extensions
            • Unsolved