Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Forum Updated on Feb 6th

    [Solved] crash. QObject::connect in a constructor of a static object instance.

    General and Desktop
    2
    6
    7441
    Loading More Posts
    • 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
      Davita last edited by

      I'm trying to find out why my app crashes for the whole day. A picture worth thousands of words, so take a look at this code:

      @class SandboxedAppStat : public QObject
      {
      Q_OBJECT

      private slots:
      void pidsTimerTimeout();

      public:
      QTimer m_PidsTimer;

      SandboxedAppStat(QObject *parent = NULL);
      

      };

      void SandboxedAppStat::pidsTimerTimeout()
      {
      qDebug() << "whatever";
      }

      SandboxedAppStat::SandboxedAppStat(QObject *parent)
      : QObject(parent)
      {
      bool b = QObject::connect(&m_PidsTimer), SIGNAL(timeout()), this, SLOT(pidsTimerTimeout()));
      m_PidsTimer.start(500);
      }@

      @class SandboxedApp : public QObject
      {
      Q_OBJECT

      private:
      static SandboxedAppStat SandboxedAppStat1;
      };

      SandboxedAppStat SandboxedApp::SandboxedAppStat1;
      @

      Actually what I'm trying to do, is to simulate static constructor behavior in C++. I want
      @QObject::connect(&m_PidsTimer), SIGNAL(timeout()), this, SLOT(pidsTimerTimeout()));
      m_PidsTimer.start(500);@

      to be called as soon as the static member SandboxedAppStat1 initializes. That's why the code shown above is in the constructor of SandboxedAppStat.
      However, my problem is that when I run the program, it crashes as soon as it reaches the line @connect(&m_PidsTimer), SIGNAL(timeout()), this, SLOT(pidsTimerTimeout()));@

      with error code c0000005 (access violation I guess).
      here's the screenshot http://dl.dropbox.com/u/3055964/Untitled.gif

      If I declare SandboxedAppStat as a non static variable, then there is no crash and no errors. everything works fine.
      First I thought that crash reason could be the fact that, static members are initialized too early for QObject::connect to be able to be called, that's why I updated SandboxedAppStat constructor with the following code:

      @ auto *t = this;
      QtConcurrent::run([&] () {
      Sleep(3000);
      bool b = QObject::connect(&(t->m_PidsTimer), SIGNAL(timeout()), t, SLOT(pidsTimerTimeout()));
      t->m_PidsTimer.start(500);
      });
      @

      As you can see, QObject::connect executes after 3 seconds when static SanboxedAppStat is initialized, but this didn't help either, the program crashes after 3 seconds.
      I'm really confused, I don't understand what can be the cause of this problem. Can't we use signal/slots in a static object instances?

      I'm using Qt 4.8.0 with MSVC 2010.

      Thanks

      1 Reply Last reply Reply Quote 0
      • A
        alexisdm last edited by

        For the first method, the problem might be that the metaobject needed for connecting the slot is not yet initialized (See "the static order initialization fiasco in the C++ FAQ":http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.14).

        It doesn't crash with gcc on linux, but it prints the error:
        @QObject::startTimer: QTimer can only be used with threads started with QThread@

        And for the second method, with the lambda, I think the crash is caused by the variable t going out of scope, and not pointing to a valid pointer at the time the connect call occurs. You could pass it as a binded parameter to run:

        @QtConcurrent::run([&] (decltype(this) t) {
        bool b = QObject::connect(&(t->m_PidsTimer), SIGNAL(timeout()), t, SLOT(pidsTimerTimeout()));
        t->m_PidsTimer.start(500);}
        , this);
        @

        1 Reply Last reply Reply Quote 0
        • D
          Davita last edited by

          @alexisdm thank you for your answer. You were right about the lambdas, I followed your suggestion and didn't had a crash after that.
          However, about static order initialization, as far as I'm aware, this can occur only if a static object/function tries to access another static object in different compilation unit. Does this mean that Qt meta object stuff is accessing my static member from a static function? And if so, why? what's the reason behind this?

          Thanks

          1 Reply Last reply Reply Quote 0
          • D
            Davita last edited by

            BTW, here's a simple project consisting of only one header and one source file to reproduce the problem. http://dl.dropbox.com/u/3055964/untitled1.zip

            1 Reply Last reply Reply Quote 0
            • A
              alexisdm last edited by

              The static data being accessed is the meta information generated by the moc for your SandboxedAppStat class, in the file moc_yourfilename.cpp.

              You could try printing the class name to confirm the problem:
              @SandboxedAppStat::SandboxedAppStat(QObject *parent)
              : QObject(parent)
              {
              std::cout << Q_FUNC_INFO << std::endl; // just to confirm we entered the function
              std::cout << "class name: " << SandboxedAppStat::staticMetaObject.className() << std::endl;
              }@
              I tested and it does crash with msvc2010, but works fine with gcc.

              1 Reply Last reply Reply Quote 0
              • D
                Davita last edited by

                @alexisdm thank you very much, your post saved me :)

                1 Reply Last reply Reply Quote 0
                • First post
                  Last post