Hi,
We Qt developers cannot figure out how to proceed from here, so let me give you
a heads-up here, so you can take matters into your own hands.
TL;DR: never pass Connection objects originally declared const to
QObject::disconnect(Connection).
The function const_cast<>s away the const of the argument to reset the d_ptr to
nullptr. It doesn't matter why, suffice to say that it's not trivial to fix
either way on the Qt side.
It _is_ trivial to fix on the user side: Just don't pass const objects.
If you don't pass const objects, you're on the safe side. Period. End of story.
If you pass const objects, but they're not _originally_ marked as const (e.g.
you're using const_iterators over a QList<Connection>, then there's also
nothing to do, but, depending on how the story unfolds, you may get deprecation
warnings in the future.
If you pass const objects _originally marked as const_ (e.g. the key of a
std::map, or an object you declared const yourself:
const auto c = QObject::connect(~~~~);
~~~~
QObject::disconnect(c); // UB!!
Then you need to take action: make the Connection object _not_ originally
const. In the case above, do
auto c = QObject::connect(~~~~); // NOT const!
if you don't control the declaration (e.g. its a key in a std::map), then DO
NOT CALL disconnect() on it. Take a copy and call disconnect() on that:
const c = QObject::connect(~~~~); // can't change this even if I tried
~~~~
auto copy = c; // take a copy
QObject::disconnect(copy); // and only disconnect() the copy
The connection will be disconnected either way, it suffices if any of the
copies of the Connection gets passed to disconnect() (but memory is held
longer, until `c` is actually destroyed, there is no way to prevent that -
that's exactly the UB).
Patch your code, and pick to all your branches. You do _not_ need to update
your production Qt. This fix even fixes it for Qt versions that are out of
support!
In all of Qt, we have so found _one_ instance of the latter. And the fix was
just to drop the const from the declaration. The vast majority is just
precautionary
- for (const auto &c : std::as_const(m_connections))
+ for (auto &c : m_connections)
QObject::disconnect(c);
In anticipation of a deprecation of the const overload. If you would like
compiler help in finding affected code, apply the patch from
https://codereview.qt-project.org/c/qt/qtbase/+/724503/4/src/corelib/kernel/qobject.h
to qobject.h (only the header, the .cpp file is just comments). You do not
need to patch your production Qt. You only need to install this patch on a
developer machine, or the CI, and fix the deprecated calls. The resulting
executable will be forward and backward compatible with the unpatched Qt.
Sorry for the annoyance, and for failing to detect the issue sooner, but this
is really only fixable at the user side.
Please help spread the word!
Thanks,
Marc
--
Marc Mutz <[email protected]><mailto:[email protected]> (he/his)
Principal Software Engineer
The Qt Company
Erich-Thilo-Str. 10 12489
Berlin, Germany
www.qt.io<http://www.qt.io>
Geschäftsführer: Mika Pälsi, Juha Varelius, Jouni Lintunen
Sitz der Gesellschaft: Berlin,
Registergericht: Amtsgericht Charlottenburg,
HRB 144331 B
Public
--
Development mailing list
[email protected]
https://lists.qt-project.org/listinfo/development