Details
-
Bug
-
Resolution: Cannot Reproduce
-
P1: Critical
-
None
-
5.5.0
-
Desktop Linux, icc 15.0
Description
Please find the test attached, it should create an app with a visible main window, and set a single shot timer to automatically quit it after running for a second or so.
It tries to connect a QTimer's timeout signal to the QApplication's quit slot by passing their object pointers and member function pointers to QObject::connect, but that fails to return a valid connection when built for x86_64 with an Intel Compiler (14.0 and 15.0 tested)
A similar problem was reported against 5.3.1 already, but was closed out:
https://bugreports.qt.io/browse/QTBUG-40281
The problem exists in the subsequent releases we've tested, up to and including the most recent, 5.5.0.
The problem is the way the Qt's new overloaded QObject::connect methods try to identify an object's signal from a member function pointer (MFP). It's based on a false assumption that MFP values can be cast to a void* values for equlity comparisons. The ISO C++ standard specifies that casting an MFP to void* is illegal and its behavior undefined. See explanation here:
https://isocpp.org/wiki/faq/pointers-to-members#cant-cvt-memfnptr-to-voidptr
Though the mechanism may happen to work with certain compilers (like GCC's) that's unreliable, and looking at GCC 4.8.1's MFP types for x86_64, they are actually 16 bytes, twice the size of a regular pointer (like void*), so only the first half of its data is actually being compared! The Intel compiler's MFP types for x86_64 are also 16 bytes.
SUGGESTED FIX:
The inline template definitions of the new overloaded QObject::connect methods that currently do the illegal casting seem to have sufficient type information to perform signal identification cleanly if the sender object's known signals were made available as a set of static tables (created by MOC say), one for each distinct signal signature used (C++ allows MFP's of the same type can be compared directly). The tables could be used to map a matched object signal MFP to its signal identifier string (i.e. what the SIGNAL() macro provides in the old syntax) for passing to the core connect implementation.