20 ways to debug Qt signals and slots

Below are some suggestions for troubleshooting signals and slots in the Qt C++ library.

1. Check for compiler warnings about non-existent signals and/or slots.

2. Use break points or qDebug to check that signal and slot code is definitely reached:
– the connect statement
– code where the signal is fired
– the slot code.

3. Check that the parameter types of the signal and slot are exactly correct and, as appropriate, that they match.

4. Make sure you haven’t added a name to the signal or slot argument: for example, use textChanged(const QString &) not textChanged(const QString &text).

5. Check that the connect argument types and syntax are correct. The connect statement should look like this:

connect(senderObject, SIGNAL(mySignal(const QString&)), receiverObject, SLOT(mySlot(const QString&)));

Check brackets, check that SIGNAL and SLOT are capitalised and that the sender and receiver are both objects, not class names.

6. Check that the signal is being fired as expected. You can do this with code like the following:
connect(this, SIGNAL(mySignal()), qApp, SLOT(aboutQt()));

7. Check that slots are declared correctly in the appropriate public/protected/private slots sections of your class declaration. Check that you’ve used private slots:, for example not slots:. Check for a colon, i.e. private slots: not private slots.

8. If you use custom signals, check that these are declared correctly, with a void return type, in the public/protected/private signals section of your class declaration.

9. Make sure the Q_OBJECT macro is inserted at the beginning of your class declaration.

10. Check that classes using signals and slots inherit QObject or a QObject subclass.

11. Make sure to run qmake after adding the Q_OBJECT macro to a class. You may need to rebuild your project.

12. Use break points or qDebug to check that slots are being called the appropriate number of times: make sure the connection isn’t made repeatedly.

13. Put all connect statements before functions calls that may fire their signals, to ensure that the connections are made before the signals are fired. For example:

   _myObj = new MyClass();
   connect(_myObj, SIGNAL(somethingHappend()), SLOT(doSomething()));


   _myObj = new MyClass();
   connect(_myObj, SIGNAL(somethingHappend()), SLOT(doSomething()));

14. Check that your connections aren’t affected by disconnect statements.

15. Don’t add a semi-colon after Q_OBJECT:




16. Check the return value of the connect statement: connect returns true if it successfully connects the signal to the slot.

17. Use QErrorMessage::qtHandler() or qInstallMsgHandler() to view connect error warnings.

18. Make sure that your slot function is declared as a slot, e.g. private slots not private.

19. Use QSignalSpy to verify signal arguments.

20. Follow Qt’s naming conventions for signals and slots:

signal: somethingHappened()
slot: doSomething()

In grammatical terms, signal names are usually constructed from a past participle: changed, pressed, etc. They describe an event or change of state that has occurred. Slot names are imperative verbs and describe an action to be done: clear, setDate, etc.


About Sam Dutton

I am a Developer Advocate for Google Chrome. I grew up in rural South Australia, went to university in Sydney, and have lived since 1986 in London, England. Twitter: @SW12
This entry was posted in Uncategorized and tagged , , , . Bookmark the permalink.

44 Responses to 20 ways to debug Qt signals and slots

  1. Newbie says:

    Thanks for this. It solved a problem I was having with signals and slots (Calling the signal in the constructor before I had connected them)

  2. Stefan says:

    Hey; I’ve got a new one. I came across this post trying to figure my problem out. Turned out I’d declared a widget inside a conditional. No wonder it disappears – it’s going out of scope! Possibly worse than that time I used = instead of ==.

  3. Anisha Kaul says:

    Thanks Sam, your blog saved my time.

  4. Ryan Cuthbertson says:

    21. Ensure the receiving objects you connect to are not getting destroyed before their slots can get called.

  5. Thanks for the post. I always put the parameter name in the connect statement and wonder, why doesn’t my program work. 😛 Saved a great deal.

  6. ANIL V says:

    Hi Sam,
    I am trying to emit the signal for same class of slot for that i have used as mentioned below in my constructor:
    connect( this,SIGNAL(send_sig(int)),this,SLOT(receiver(int));
    From the one of same class member i am emitting sigma but the slot is not getting calling. I have verified this with the qDebug();

    Can you please help me in this ?


  7. Jamie says:

    Awesome! Your article (in particular point 4) just saved me a lot of effort debugging some signal/slot issues in my BB10 Cascades app.

  8. Brian says:

    Thanks! I didn’t declare the slot and this checklist saved me. I’d forgotten how time consuming C++ development is 😀

  9. Pingback: Qt 4′ten Qt 5′e Geçiş | D. Barış Akkurt

  10. Number 5 was the key for me. Thanks so much!

  11. Jay says:

    Helpful article , it helped alot after reading this article solved the 6 hrs screwing problem.

  12. Thank you very much for the post. Excellent advice and has helped me out of more than one bind at this point.

  13. Someone says:

    To extend on >Ryan Cuthbertson – 27 January, 2012 at 4:02 am – “21. …”<:
    This could also be the case when re-emitting a signal, in my case, the re-emitting object (and its original signal source child) was created locally in the main window constructor. Creating it with the new keyword fixed the problem..

  14. John says:

    Thanks for the posting, let me add my own in case it saves someone else the hours I wasted.

    23 Don’t instantiate objects using symbols until after the QApplication object is created. Seems obvious but I put my single instance code at the top of my main and then had a heck of a time figuring out why nothing was emitting signals.


  15. Colin Hobday says:

    I have the following…

    m_phone = new Phone(this);
    connect( m_phone, SIGNAL(callUpdated(const bb::system::phone::Call &)), this, SLOT(callUpdated(const bb::system::phone::Call &)));//,Qt::QueuedConnection);
    connect(m_phone,SIGNAL(lineUpdated(const bb::system::phone::Line &)),this,SLOT(lineUpdated(const bb::system::phone::Line &)),Qt::QueuedConnection);
    connect(m_phone,SIGNAL(lineRemoved(const bb::system::phone::Line &)),this,SLOT(lineRemoved(const bb::system::phone::Line &)),Qt::QueuedConnection);
    callUpdated works just fine – but I NEVER get a lineUpdated or lineRemoved signal. Can you tell why this is.
    I need lineUpdated to work as the info I want is in the Line object – but will only be populated once the lineUpdated signal has fired.

    Any ideas would be useful.

  16. elyse prewitte says:

    Many thanks, this was a lifesaver.

  17. rigo says:

    Thank you for this great article!
    On my browser, the formatting seems to get garbled after point 13.

  18. Sisira Jayasinghe says:

    I am glad I googled my way into your page. I mistake was item 5. Thank you so much.

  19. juanjuan says:

    Great one !!

  20. Miek Vincent says:

    This is useful, thanks.

    I’m a long time Delphi programmer, but new to Qt. What I don’t understand, coming from strongly typed Object Pascal, is why the compiler doesn’t pick up some of the errors for me.

    It took me ages to realise that I needed to specify the parameters types of signal and slot in the connect statement. And when they weren’t there or the types I needed my application would still compile, but the connection would not be made at run time.

    What might be useful is an article with some of the errors and warnings that the compiler does manage to spot for the different checks that you’ve suggested in this article.

    • IInspectable says:

      The reason, the compiler cannot spot errors is, that the plumbing underneath the signal-slot infrastructure is based on tables with character strings as the keys. The SIGNAL and SLOT macros convert the arguments into string representations. After that’s done, the compiler has no more semantic information, and cannot perform any checks.

      Starting with Qt5 there is a new signal and slot syntax, based on function pointers instead of character strings (see http://doc.qt.io/qt-5/signalsandslots.html). The implementation makes heavy use of templates, and errors the compiler can spot, lead to insanely cryptic error messages. Plus, the syntax for using overloads lost succinctness, requiring an additional cast operator.

      The current state of affairs is still: Signals and slots are convenient, easy to get wrong, and nigh impossible to debug.

  21. mr3 says:

    Thanks Sam, 7 years later and you just helped me sniff out a slot issue. You da man.

  22. foobar says:

    I spent a long time to solve this problem:
    I passed a custom Object “MyObject” as an argument and forgot to call


    There was no warning. It just ignored the connection. I think it’s worth to include this one into your list!

    • gavaz says:

      OH yes! I’ve had the same issue and spent a whole day to find the reason. Unfortunately I found this comment only after fixing the issue. It would be nice to put the qRegisterMetaType it on the list above!

  23. IInspectable says:

    This blog entry contains extremely valuable information, but it doesn’t hold, what the title promises. The list of DONTs is essentially saying: Don’t write bugs.

    However, bugs do happen, on occasion. And that’s where you need proper tools and strategies to diagnose the issue. I was hoping to find either one in this article. This is not the case, however, and when things break you are still left with a call stack, 70 levels deep, without the slightest clue, how you got there. Neither signal/slot signatures are immediately visible (due to the stringizing nature of the SIGNAL and SLOT macros), nor is there an easy way (or, really, any way at all) to match up the slot invocation to a particular connect call. These are common scenarios in any Qt project.

    Is it really impossible to (effectively) debug Qt applications, or am I just missing the tools and strategies?

    • mr3 says:

      That’s a good point. What I do when things aren’t working in Qt and I don’t know why: debug Qt source. I’ve gotten to the point with a few features where I can watch Qt execute and know pretty quickly what’s gone wrong. It’s brute force, but it could suggest one or more key places in source where you can reliably breakpoint and check state quickly. Another option might be turning on Qt’s logging, but I’ve never tried it or even seen its code doing it in the places where I’ve debugged.

  24. ayman says:

    I would add another issue I encountered. I did the following:
    connect( obj,SIGNAL(send_sig((int))),this,SLOT(receiver((int)));

    It looks fine at first, BUT there are double parentheses around the parameters, and for some reason that made my signal obsolete and never fired. Hope that helps people.

  25. Severin Puschkarski says:

    25: Check if you called your class which inherits from QObject with new!

    After all the other 24 points from this page were correct and quite some hours, I discovered this finally…

  26. ed says:

    Used an abstraction as workaround to get templates AND moc Slots/Signals

    I required the classes that the template supported to conform to the same interface (e.g., T::subtype, implement T::memberFnNameA, T::memberFnNameB). Then I had to overload the prototypes with each different datatype. E.g.,

    memberFnNameA( DataType1& );
    memberFnNameA( DataType2& );
    memberFnNameA( DataType3& );

    memberFnNameB( DataType1& );
    memberFnNameB( DataType2& );
    memberFnNameB( DataType3& );

    This worked fine, and I could use template specialization in cases where it did not.

    I think I ran into problems sometimes when the order of a non templated slot came after the templated slots (resolved by placing before the other ones). The error wasn’t related at all — it complained the connect() args were a mismatch (the types were not a mistmatch). Anyway, pretty tricky, but works well.

  27. Bernd says:

    Another hint:
    I got signal not found messages, as I was using the new signal/slot syntax for a class in a DLL that was conneted to from a class in the app: connect(overrideDialog,&OverrideDialog::overrideCancelled,this,&ArrivalReportContent::overrideCancelled);
    Changing it to the old syntax fixed it magically:

    I think the qt stuff is still a bit buggy somehow. Especially because I used the DLL from two similar apps (Arrival- and Departure Report) and one is running OK with the new syntax and the other not)

  28. Thanks a lot! Your 13th point solved me a problem 🙂 I mentioned it on stackoverflow.

  29. Glenn says:

    Ten years later, you have saved my ass! I wrote SLOT(foo) instead of SLOT(foo()) and I caught it on step 3 when checking parameter types. Why doesn’t that warn? 😦 Thanks!

  30. Frederico Damian says:

    Could you explain why is 4) a thing? I search QT Signal & Slots documentation and didn’t found it. Also thank you for your content.

    • Sam Dutton says:

      I haven’t used Qt for about eight years, but IIRC the point was to specify a type and not (inadvertently) add a name like you would for a parameter to a function.

  31. Dmitry Chikov says:

    21. And QObject have to be created from the same thread.

  32. Hamza Mehmood says:

    Adding to this amazing article ❤ , it helped me a lot. Thank you

    25. Make sure the the classes are initialized before adding signal and slot. i.e you can add a singleshot Qtimer to call your slot functions.

    My scenario : in my case i used two different ui forms and prompted the widgets into mainwindow..I tried to connect them using signals and slot.. but it didn't work. So i added a delay before connecting the signal and slots.

    let me know if anyone needs help regarding such scenario …

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.