diff --git a/modules/gui/qt/qt.cpp b/modules/gui/qt/qt.cpp
index 57d25ed5dc147a9aa868e39a2bddd3fbb14eb931..3265a2637c51030058c6ce70e32e189057fbdc64 100644
--- a/modules/gui/qt/qt.cpp
+++ b/modules/gui/qt/qt.cpp
@@ -1027,11 +1027,12 @@ static void *Thread( void *obj )
     p_intf->p_mainPlaylistController = new vlc::playlist::PlaylistController(p_intf->p_playlist);
 
     std::unique_ptr<ModelRecoveryAgent> playlistModelRecoveryAgent;
-    QMetaObject::invokeMethod(&app, [&playlistModelRecoveryAgent, p_intf]() {
+    QMetaObject::invokeMethod(&app, [&playlistModelRecoveryAgent, settings = p_intf->mainSettings, playlistController = p_intf->p_mainPlaylistController]() {
         try {
-            playlistModelRecoveryAgent = std::make_unique<ModelRecoveryAgent>(p_intf->mainSettings,
-                                                                              QStringLiteral("Playlist"),
-                                                                              p_intf->p_mainPlaylistController);
+            if (Q_LIKELY(settings && playlistController))
+                playlistModelRecoveryAgent = std::make_unique<ModelRecoveryAgent>(settings,
+                                                                                  QStringLiteral("Playlist"),
+                                                                                  playlistController);
         } catch (...){ }
     }, Qt::QueuedConnection);
 
@@ -1087,7 +1088,6 @@ static void *Thread( void *obj )
         {
             msg_Err(p_intf, "unable to create main interface");
             delete p_intf->p_mi;
-            p_intf->p_mi = nullptr;
             //process deleteLater events as the main loop will never run
             QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
             return ThreadCleanup( p_intf, CLEANUP_ERROR );
@@ -1180,32 +1180,20 @@ static void *ThreadCleanup( qt_intf_t *p_intf, CleanupReason cleanupReason )
     MediaSourceCache::killInstance();
 
     //destroy MainCtx, Compositor shouldn't not use MainCtx after `unloadGUI`
-    if (p_intf->p_mi) {
-        delete p_intf->p_mi;
-        p_intf->p_mi = nullptr;
-    }
+    delete p_intf->p_mi;
 
     if ( p_intf->p_compositor &&  cleanupReason == CLEANUP_APP_TERMINATED)
     {
         p_intf->p_compositor.reset();
 
         delete p_intf->mainSettings;
-        p_intf->mainSettings = nullptr;
     }
 
     /* Destroy the main playlist controller */
-    if (p_intf->p_mainPlaylistController)
-    {
-        delete p_intf->p_mainPlaylistController;
-        p_intf->p_mainPlaylistController = nullptr;
-    }
+    delete p_intf->p_mainPlaylistController;
 
     /* Destroy the main InputManager */
-    if (p_intf->p_mainPlayerController)
-    {
-        delete p_intf->p_mainPlayerController;
-        p_intf->p_mainPlayerController = nullptr;
-    }
+    delete p_intf->p_mainPlayerController;
 
     /* Delete the application automatically */
     return NULL;
diff --git a/modules/gui/qt/qt.hpp b/modules/gui/qt/qt.hpp
index b2a400e91e359299ba4f01a81a184253d2bde916..373522df7d45fe1c32a66feba0a7a84c075efc6a 100644
--- a/modules/gui/qt/qt.hpp
+++ b/modules/gui/qt/qt.hpp
@@ -37,6 +37,7 @@
 #include <qconfig.h>
 
 #include <QString>
+#include <QPointer>
 
 enum {
     IMEventTypeOffset     = 0,
@@ -83,15 +84,15 @@ struct qt_intf_t
 
     vlc_thread_t thread;
 
-    class MainCtx *p_mi;     /* Main Interface, NULL if DialogProvider Mode */
-    class QSettings *mainSettings; /* Qt State settings not messing main VLC ones */
+    QPointer<class MainCtx> p_mi;     /* Main Interface, NULL if DialogProvider Mode */
+    QPointer<class QSettings> mainSettings; /* Qt State settings not messing main VLC ones */
 
     bool b_isDialogProvider; /* Qt mode or Skins mode */
 
     vlc_playlist_t *p_playlist;  /* playlist */
     vlc_player_t *p_player; /* player */
-    vlc::playlist::PlaylistController* p_mainPlaylistController;
-    PlayerController* p_mainPlayerController;
+    QPointer<vlc::playlist::PlaylistController> p_mainPlaylistController;
+    QPointer<PlayerController> p_mainPlayerController;
     std::unique_ptr<vlc::Compositor>  p_compositor;
 
     int refCount;
@@ -116,8 +117,8 @@ public:
 };
 
 #define THEDP DialogsProvider::getInstance()
-#define THEMIM p_intf->p_mainPlayerController
-#define THEMPL p_intf->p_mainPlaylistController
+#define THEMIM p_intf->p_mainPlayerController.get()
+#define THEMPL p_intf->p_mainPlaylistController.get()
 
 #define qfu( i ) QString::fromUtf8( i )
 #define qfue( i ) QString::fromUtf8( i ).replace( "&", "&&" ) /* for actions/buttons */
diff --git a/modules/gui/qt/util/model_recovery_agent.hpp b/modules/gui/qt/util/model_recovery_agent.hpp
index 3e2f36462e4d6511056c0605fb5bc79c581fcd2d..5435bd50eb9d0e3aaaa23382840de580b2ed7757 100644
--- a/modules/gui/qt/util/model_recovery_agent.hpp
+++ b/modules/gui/qt/util/model_recovery_agent.hpp
@@ -45,7 +45,7 @@ class ModelRecoveryAgent
 public:
     // NOTE: settings and model must outlive the instance of this class.
     template<class T>
-    ModelRecoveryAgent(class QSettings *settings, const QString& modelIdentifier, T* model)
+    ModelRecoveryAgent(QPointer<QSettings> settings, const QString& modelIdentifier, QPointer<T> model)
         : m_settings(settings), m_key(modelIdentifier + QStringLiteral("/RecoveryFilePath"))
     {
         assert(settings);