diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 50e325702..520e42f78 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -61,6 +61,7 @@ set(SHARED_SOURCES "OSInfo.cpp" "PasswordGenerator.cpp" "PlatformCheck.cpp" + "QtUtils.cpp" "SelfSignedCertificate.cpp" "ServerAddress.cpp" "ServerResolver.cpp" diff --git a/src/QtUtils.cpp b/src/QtUtils.cpp new file mode 100644 index 000000000..a248af742 --- /dev/null +++ b/src/QtUtils.cpp @@ -0,0 +1,10 @@ +// Copyright 2021 The Mumble Developers. All rights reserved. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file at the root of the +// Mumble source tree or at . + +#include + +void deleteQObject(QObject *object) { + object->deleteLater(); +} diff --git a/src/QtUtils.h b/src/QtUtils.h new file mode 100644 index 000000000..d53c243c0 --- /dev/null +++ b/src/QtUtils.h @@ -0,0 +1,20 @@ +// Copyright 2021 The Mumble Developers. All rights reserved. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file at the root of the +// Mumble source tree or at . + +#ifndef MUMBLE_QTUTILS_H_ +#define MUMBLE_QTUTILS_H_ + +class QObject; + +/** + * A deleter function to be used for QObjects that must not be deleted using + * delete directly but rather by calling deleteLater() on them (and thus letting + * Qt perform the actual deletion). + * + * This function is intended to be used in smart-pointers holding QObjects. + */ +void deleteQObject(QObject *object); + +#endif // MUMBLE_QTUTILS_H_ diff --git a/src/mumble/MainWindow.h b/src/mumble/MainWindow.h index 8d04221b9..ae473b2a8 100644 --- a/src/mumble/MainWindow.h +++ b/src/mumble/MainWindow.h @@ -70,7 +70,7 @@ public: qiIconMuteSuppressed; QIcon qiTalkingOn, qiTalkingWhisper, qiTalkingShout, qiTalkingOff; QMap< unsigned int, UserLocalVolumeDialog * > qmUserVolTracker; - std::unordered_map< unsigned int, std::unique_ptr< UserLocalNicknameDialog > > qmUserNicknameTracker; + std::unordered_map< unsigned int, NicknameDialogPtr > qmUserNicknameTracker; /// "Action" for when there are no actions available QAction *qaEmpty; diff --git a/src/mumble/UserLocalNicknameDialog.cpp b/src/mumble/UserLocalNicknameDialog.cpp index afb43bc88..9e59cd42d 100644 --- a/src/mumble/UserLocalNicknameDialog.cpp +++ b/src/mumble/UserLocalNicknameDialog.cpp @@ -17,7 +17,7 @@ UserLocalNicknameDialog::UserLocalNicknameDialog( unsigned int sessionId, - std::unordered_map< unsigned int, std::unique_ptr< UserLocalNicknameDialog > > &qmUserNicknameTracker) + std::unordered_map< unsigned int, NicknameDialogPtr > &qmUserNicknameTracker) : QDialog(nullptr), m_clientSession(sessionId), m_qmUserNicknameTracker(qmUserNicknameTracker) { setupUi(this); @@ -49,13 +49,14 @@ void UserLocalNicknameDialog::closeEvent(QCloseEvent *event) { void UserLocalNicknameDialog::present( unsigned int sessionId, - std::unordered_map< unsigned int, std::unique_ptr< UserLocalNicknameDialog > > &qmUserNicknameTracker) { + std::unordered_map< unsigned int, NicknameDialogPtr > &qmUserNicknameTracker) { if (qmUserNicknameTracker.find(sessionId) != qmUserNicknameTracker.end()) { qmUserNicknameTracker.at(sessionId)->show(); qmUserNicknameTracker.at(sessionId)->raise(); } else { - std::unique_ptr< UserLocalNicknameDialog > userNickname = - std::make_unique< UserLocalNicknameDialog >(sessionId, qmUserNicknameTracker); + // Make sure to use the custom deleter for QObjects that calls deleteLater() on them instead of using + // delete directly as the latter can lead to segmentation faults. + NicknameDialogPtr userNickname(new UserLocalNicknameDialog(sessionId, qmUserNicknameTracker), deleteQObject); userNickname->show(); qmUserNicknameTracker.insert(std::make_pair(sessionId, std::move(userNickname))); } diff --git a/src/mumble/UserLocalNicknameDialog.h b/src/mumble/UserLocalNicknameDialog.h index 7655135f6..b3b91ac72 100644 --- a/src/mumble/UserLocalNicknameDialog.h +++ b/src/mumble/UserLocalNicknameDialog.h @@ -6,12 +6,22 @@ #ifndef MUMBLE_MUMBLE_USERNICKNAME_H_ #define MUMBLE_MUMBLE_USERNICKNAME_H_ +#include "QtUtils.h" + #include #include #include "ClientUser.h" #include "ui_UserLocalNicknameDialog.h" +class UserLocalNicknameDialog; + +/** + * A typedef for a unique pointer (std::unique_ptr) using the deleter-function dedicated for QObjects + * instead of using raw delete + */ +typedef std::unique_ptr< UserLocalNicknameDialog, decltype(&deleteQObject) > NicknameDialogPtr; + class UserLocalNicknameDialog : public QDialog, private Ui::UserLocalNicknameDialog { Q_OBJECT Q_DISABLE_COPY(UserLocalNicknameDialog); @@ -21,7 +31,7 @@ class UserLocalNicknameDialog : public QDialog, private Ui::UserLocalNicknameDia /// The user's original nickname when entering the dialog. QString m_originalNickname; - std::unordered_map< unsigned int, std::unique_ptr< UserLocalNicknameDialog > > &m_qmUserNicknameTracker; + std::unordered_map< unsigned int, NicknameDialogPtr > &m_qmUserNicknameTracker; public slots: void closeEvent(QCloseEvent *event); @@ -32,10 +42,10 @@ public slots: public: static void present(unsigned int sessionId, - std::unordered_map< unsigned int, std::unique_ptr< UserLocalNicknameDialog > > &qmUserNicknameTracker); + std::unordered_map< unsigned int, NicknameDialogPtr > &qmUserNicknameTracker); UserLocalNicknameDialog( unsigned int sessionId, - std::unordered_map< unsigned int, std::unique_ptr< UserLocalNicknameDialog > > &qmUserNicknameTracker); + std::unordered_map< unsigned int, NicknameDialogPtr > &qmUserNicknameTracker); }; #endif