Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When Qt-5 will fail the connect

Tags:

qt

qt5

Reading Qt signal & slots documentation, it seems that the only reason for a new style connection to fail is: "If there is already a duplicate (exact same signal to the exact same slot on the same objects), the connection will fail and connect will return false"

Which means that connection was already successful the first time and does not allow multi-connections when using Qt::UniqueConnection.

Does this means that Qt-5 style connection will always success? Are there any other reasons for failure?

like image 215
user3360767 Avatar asked Apr 19 '17 06:04

user3360767


2 Answers

The new-style connect can still fail at runtime for a variety of reasons:

  • Either sender or receiver is a null pointer. Obviously this requires a check that can only happen at runtime.
  • The PMF you specified for a signal is not actually a signal. Lacking proper C++ reflection capabilities, all you can do at compile time is checking that the signal is a non-static member function of the sender's class.

    However, that's not enough to make it a signal: it also needs to be in a signals: section in your class definition. When moc sees your class definition, it will generate some metadata containing the information that that function is indeed a signal. So, at runtime, the pointer passed to connect is looked up in a table, and connect itself will fail if the pointer is not found (because you did not pass a signal).

  • The check on the previous point actually requires a comparison between pointers to member functions. It's a particularly tricky one, because it will typically involve different TUs:

    1. one is the TU containing moc-generated data (typically a moc_class.cpp file). In this TU there's the aforementioned table containing, amongst other things, pointers to the signals (which are just ordinary member functions).
    2. is the TU where you actually invoke connect(sender, &Sender::signal, ...), which generates the pointer that gets looked up in the table.

    Now, the two TUs may be in the same application, or perhaps one is in a library and the other in your application, or maybe in two libraries, etc; your platform's ABI starts to get into play.

    In theory, the pointers stored when doing 1. are identical to the pointers generated when doing 2.; in practice, we've found cases where this does not happen (cf. this bug report that I reported some time ago, where older versions of GNU ld on ARM generated code that failed the comparison).

    For Qt this meant disabling certain optimizations and/or passing some extra flags to the places where we know this to happen and break user software. For instance, as of Qt 5.9, there is no support for -Bsymbolic* flags on GCC on anything but x86 and x86-64.

    Of course, this does not mean we've found and fixed all the possible places. New compilers and more aggressive optimizations might trigger this bug again in the future, making connect return false, even when everything is supposed to work.

like image 62
peppe Avatar answered Nov 01 '22 23:11

peppe


Yes it can fail if either sender or receiver are not valid objects (nullptr for example)

Example

QObject* obj1 = new QObject();
QObject* obj2 = new QObject();
// Will succeed
connect(obj1, &QObject::destroyed, obj2, &QObject::deleteLater);
delete obj1;
obj1 = nullptr;
// Will fail even if it compiles
connect(obj1, &QObject::destroyed, obj2, &QObject::deleteLater);
like image 25
CJCombrink Avatar answered Nov 02 '22 00:11

CJCombrink