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. qobject_cast and dynamic cast fail, while static_cast seems to work

qobject_cast and dynamic cast fail, while static_cast seems to work

Scheduled Pinned Locked Moved General and Desktop
qobjectcastdynamiccaststaticcastqsslsocketdisconnected
8 Posts 3 Posters 6.0k 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.
  • B Offline
    B Offline
    Bart_Vandewoestyne
    wrote on 12 Oct 2015, 12:06 last edited by Bart_Vandewoestyne 10 Dec 2015, 12:07
    #1

    I have a class ClientSslSocket that is derived from QSslSocket and has the Q_OBJECT macro:

    class ClientSslSocket : public QSslSocket
    {
        Q_OBJECT
        ...
    };
    

    Somewhere in a method of another class FooBar, the disconnected() signal of this class is connected to the disconnectedCallback() slot in FooBar:

    bool FooBar::initializeSocket(ClientSslSocket* socket)
    {
        ...
        connect(socket, SIGNAL(disconnected()), this, SLOT(disconnectedCallback()));
        ....
    }
    

    In the disconnectedCallback() slot, I noticed that dynamic_cast and qobject_cast did not work, but static_cast does seem to work as expected:

    ClientSslSocket* sender1 = dynamic_cast<ClientSslSocket*>(sender());  // returns 0
    ClientSslSocket* sender2 = qobject_cast<ClientSslSocket*>(sender());  // returns 0
    ClientSslSocket* sender3 = static_cast<ClientSslSocket*>(sender());  // seems to work...
    

    I don't understand or see why qobject_cast and dynamic_cast return 0 here, indicating that the qobject/dynamic cast didn't succeed... although this looks like a simple signal-slot connection. What am I overlooking here, or what should I look for to diagnose this any further?

    Kind regards,
    Bart

    1 Reply Last reply
    0
    • J Offline
      J Offline
      JKSH
      Moderators
      wrote on 12 Oct 2015, 12:44 last edited by
      #2

      Add qDebug() << sender(). What do you see?

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

      B 1 Reply Last reply 12 Oct 2015, 13:48
      0
      • Y Offline
        Y Offline
        yeckel
        wrote on 12 Oct 2015, 12:45 last edited by
        #3

        Hi Bart,

        qobject_cast should work as long as everything is QObject inherited. I've tested your code and
        SlientSslSocket* sender2 = qobject_cast<SlientSslSocket*>(sender());
        and it's working (qt 5.5, gcc 4.8.4). I thing there might be problem how is your socket for the method initializeSocket(ClientSslSocket* socket) created. Could you paste longer example?

        B 1 Reply Last reply 12 Oct 2015, 14:10
        0
        • J JKSH
          12 Oct 2015, 12:44

          Add qDebug() << sender(). What do you see?

          B Offline
          B Offline
          Bart_Vandewoestyne
          wrote on 12 Oct 2015, 13:48 last edited by
          #4

          @JKSH said:

          Add qDebug() << sender(). What do you see?

          This gives me

          QSslSocket(0x4b1e370)
          

          I do not understand why I have a QSslSocket here. I am expecting a `ClientSslSocket' object, because basically, the structure of the code is as follows (I cannot literally copy-paste due to company restrictions):

          bool Foo::initializeSocket(ClientSslSocket* socket)
          {
              ....
              connect(socket, SIGNAL(disconnected()), this, SLOT(disconnectedCallback()));
              ....
          }
          

          If I go up one level in the call stack, then I see that the initializeSocket function gets called as follows:

          ClientSslSocket* socket = new ClientSslSocket();
          if ( initializeSocket(socket)== true )
          { ... }
          

          so for as far as I can see, it gets a pointer to a ClientSslSocket object... I'm puzzled and don't see what I'm overlooking. Could it be something in the implementation of ClientSslSocket that I'm forgetting?

          1 Reply Last reply
          0
          • Y yeckel
            12 Oct 2015, 12:45

            Hi Bart,

            qobject_cast should work as long as everything is QObject inherited. I've tested your code and
            SlientSslSocket* sender2 = qobject_cast<SlientSslSocket*>(sender());
            and it's working (qt 5.5, gcc 4.8.4). I thing there might be problem how is your socket for the method initializeSocket(ClientSslSocket* socket) created. Could you paste longer example?

            B Offline
            B Offline
            Bart_Vandewoestyne
            wrote on 12 Oct 2015, 14:10 last edited by
            #5

            @yeckel Do you have the code of your test-program available somewhere? I would like to test it on my platform...

            Y 1 Reply Last reply 12 Oct 2015, 15:47
            0
            • B Bart_Vandewoestyne
              12 Oct 2015, 14:10

              @yeckel Do you have the code of your test-program available somewhere? I would like to test it on my platform...

              Y Offline
              Y Offline
              yeckel
              wrote on 12 Oct 2015, 15:47 last edited by
              #6

              @Bart_Vandewoestyne https://drive.google.com/file/d/0B6MSAirH9oMIZi0xNkI5QkFGWnc/view?usp=sharing

              1 Reply Last reply
              0
              • B Offline
                B Offline
                Bart_Vandewoestyne
                wrote on 12 Oct 2015, 21:16 last edited by
                #7

                After some more debugging, I think I figured out the problem. It turns out that the FooBar class has another data structure which also holds pointers to ClientSslSockets, and FooBar's destructor looks as follows:

                FooBar::~FooBar()
                {
                    for (int i = 0; i < theList.size(); ++i)
                    {
                        if (theList.at(i).socket)
                        {
                #ifdef linux
                            theList.at(i).socket->close();
                #else
                            delete TheList.at(i).mpSocket;
                #endif
                            mvConnectionInfoList.at(i).mpSocket = NULL;
                        }
                    }
                }
                

                I'm on Windows, and from what I can debug right now, it seems that the line

                delete TheList.at(i).mpSocket;
                

                is causing the ClientSslSocket destructor being called. And apparently, that same delete statement also triggers the disconnect() signal so that the disconnectedCallback() slot is called, apparently with an already partly destructed sender object (that is my educated guess, I found out that the ClientSslSocket destructor is called before the slot is handled...).

                So I have some more questions now:

                1. Could my educated guess be correct?
                2. Does anybody have any idea why the original author of this code decided to make a difference between linux and non-linux? If I remove the ifdef and simply use close() in all situations, things seem to work, although it seems that in this case the ClientSslSocket destructor is no longer called (and I'm not sure if this is a good thing...).
                3. What would be the clean solution here? How should FooBar's destructor look like?

                Thanks for bearing with me ;-)
                Bart

                J 1 Reply Last reply 12 Oct 2015, 22:50
                0
                • B Bart_Vandewoestyne
                  12 Oct 2015, 21:16

                  After some more debugging, I think I figured out the problem. It turns out that the FooBar class has another data structure which also holds pointers to ClientSslSockets, and FooBar's destructor looks as follows:

                  FooBar::~FooBar()
                  {
                      for (int i = 0; i < theList.size(); ++i)
                      {
                          if (theList.at(i).socket)
                          {
                  #ifdef linux
                              theList.at(i).socket->close();
                  #else
                              delete TheList.at(i).mpSocket;
                  #endif
                              mvConnectionInfoList.at(i).mpSocket = NULL;
                          }
                      }
                  }
                  

                  I'm on Windows, and from what I can debug right now, it seems that the line

                  delete TheList.at(i).mpSocket;
                  

                  is causing the ClientSslSocket destructor being called. And apparently, that same delete statement also triggers the disconnect() signal so that the disconnectedCallback() slot is called, apparently with an already partly destructed sender object (that is my educated guess, I found out that the ClientSslSocket destructor is called before the slot is handled...).

                  So I have some more questions now:

                  1. Could my educated guess be correct?
                  2. Does anybody have any idea why the original author of this code decided to make a difference between linux and non-linux? If I remove the ifdef and simply use close() in all situations, things seem to work, although it seems that in this case the ClientSslSocket destructor is no longer called (and I'm not sure if this is a good thing...).
                  3. What would be the clean solution here? How should FooBar's destructor look like?

                  Thanks for bearing with me ;-)
                  Bart

                  J Offline
                  J Offline
                  JKSH
                  Moderators
                  wrote on 12 Oct 2015, 22:50 last edited by
                  #8

                  @Bart_Vandewoestyne said:

                  1. Could my educated guess be correct?

                  Your guess sounds reasonable to me.

                  1. Does anybody have any idea why the original author of this code decided to make a difference between linux and non-linux? If I remove the ifdef and simply use close() in all situations, things seem to work, although it seems that in this case the ClientSslSocket destructor is no longer called (and I'm not sure if this is a good thing...).

                  Nope, sorry. Are there any comments in the code, or in the commit history? Could you ask the author directly?

                  1. What would be the clean solution here? How should FooBar's destructor look like?

                  It's hard to say without knowing how the rest of the program is designed. Maybe you can manually disconnect the socket before deleting it?

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

                  1 Reply Last reply
                  0

                  4/8

                  12 Oct 2015, 13:48

                  • Login

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