浏览代码

Fixed memory leak in ctkPluginArchive.

The lifetime of ctkPluginArchive instances is usually bound to
the corresponding ctkPlugin instances. In case of updating a plug-in,
the old ctkPluginArchive instance must still be kept alive. So we handle
the liftime via QSharedPointer references.
Sascha Zelzer 13 年之前
父节点
当前提交
98edffbb2b

+ 1 - 1
Libs/PluginFramework/ctkPlugin.cpp

@@ -49,7 +49,7 @@ void ctkPlugin::init(ctkPluginPrivate* dd)
 //----------------------------------------------------------------------------
 void ctkPlugin::init(const QWeakPointer<ctkPlugin>& self,
                      ctkPluginFrameworkContext* fw,
-                     ctkPluginArchive* pa)
+                     QSharedPointer<ctkPluginArchive> pa)
 {
   if (d_ptr) throw std::logic_error("ctkPlugin already initialized");
   d_ptr = new ctkPluginPrivate(self, fw, pa);

+ 1 - 1
Libs/PluginFramework/ctkPlugin.h

@@ -811,7 +811,7 @@ protected:
 
   ctkPlugin();
   void init(ctkPluginPrivate* dd);
-  void init(const QWeakPointer<ctkPlugin>& self, ctkPluginFrameworkContext* fw, ctkPluginArchive* ba);
+  void init(const QWeakPointer<ctkPlugin>& self, ctkPluginFrameworkContext* fw, QSharedPointer<ctkPluginArchive> ba);
 };
 
 /**

+ 1 - 1
Libs/PluginFramework/ctkPluginArchiveSQL.cpp

@@ -41,7 +41,7 @@ ctkPluginArchiveSQL::ctkPluginArchiveSQL(ctkPluginStorageSQL* pluginStorage,
 }
 
 //----------------------------------------------------------------------------
-ctkPluginArchiveSQL::ctkPluginArchiveSQL(ctkPluginArchiveSQL* old, int generation,
+ctkPluginArchiveSQL::ctkPluginArchiveSQL(QSharedPointer<ctkPluginArchiveSQL> old, int generation,
                                          const QUrl &pluginLocation, const QString &localPluginPath)
   : key(-1), autostartSetting(old->autostartSetting), id(old->id), generation(generation)
   , startLevel(0), location(pluginLocation), localPluginPath(localPluginPath)

+ 2 - 1
Libs/PluginFramework/ctkPluginArchiveSQL_p.h

@@ -57,7 +57,8 @@ public:
    * Construct new bundle archive in an existing bundle archive.
    *
    */
-  ctkPluginArchiveSQL(ctkPluginArchiveSQL* old, int generation, const QUrl& pluginLocation, const QString& localPluginPath);
+  ctkPluginArchiveSQL(QSharedPointer<ctkPluginArchiveSQL> old, int generation,
+                      const QUrl& pluginLocation, const QString& localPluginPath);
 
 
   /**

+ 1 - 1
Libs/PluginFramework/ctkPluginArchive_p.h

@@ -55,6 +55,7 @@ public:
    */
   static const QString AUTOSTART_SETTING_ACTIVATION_POLICY; // = "activation_policy"
 
+  virtual ~ctkPluginArchive() {}
 
   /**
    * Get an attribute from the manifest of a plugin.
@@ -185,7 +186,6 @@ public:
 
   /**
    * Remove plugin from persistent storage.
-   * This will delete the current ctkPluginArchive instance.
    */
   virtual void purge() = 0;
 

+ 2 - 3
Libs/PluginFramework/ctkPluginFrameworkContext.cpp

@@ -120,10 +120,9 @@ void ctkPluginFrameworkContext::init()
 
   log() << "Installed plugins:";
   // Use the ordering in the plugin storage to get a sorted list of plugins.
-  QList<ctkPluginArchive*> allPAs = storage->getAllPluginArchives();
-  for (int i = 0; i < allPAs.size(); ++i)
+  QList<QSharedPointer<ctkPluginArchive> > allPAs = storage->getAllPluginArchives();
+  foreach (QSharedPointer<ctkPluginArchive> pa, allPAs)
   {
-    ctkPluginArchive* pa = allPAs[i];
     QSharedPointer<ctkPlugin> plugin = plugins->getPlugin(pa->getPluginLocation().toString());
     log() << " #" << plugin->getPluginId() << " " << plugin->getSymbolicName() << ":"
         << plugin->getVersion() << " location:" << plugin->getLocation();

+ 4 - 5
Libs/PluginFramework/ctkPluginPrivate.cpp

@@ -86,7 +86,7 @@ void ctkPluginPrivate::LockObject::wakeOne()
 ctkPluginPrivate::ctkPluginPrivate(
     QWeakPointer<ctkPlugin> qq,
     ctkPluginFrameworkContext* fw,
-    ctkPluginArchive* pa)
+    QSharedPointer<ctkPluginArchive> pa)
       : q_ptr(qq), fwCtx(fw), id(pa->getPluginId()),
       location(pa->getPluginLocation().toString()), state(ctkPlugin::INSTALLED),
       archive(pa), pluginContext(0), pluginActivator(0), pluginLoader(pa->getLibLocation()),
@@ -169,7 +169,6 @@ ctkPluginPrivate::ctkPluginPrivate(QWeakPointer<ctkPlugin> qq,
 ctkPluginPrivate::~ctkPluginPrivate()
 {
   qDeleteAll(require);
-  delete archive;
 }
 
 //----------------------------------------------------------------------------
@@ -484,7 +483,7 @@ void ctkPluginPrivate::update0(const QUrl& updateLocation, bool wasActive)
 {
   const bool wasResolved = state == ctkPlugin::RESOLVED;
   const int oldStartLevel = getStartLevel();
-  ctkPluginArchive* newArchive = 0;
+  QSharedPointer<ctkPluginArchive> newArchive;
 
   operation.fetchAndStoreOrdered(UPDATING);
   try
@@ -517,7 +516,7 @@ void ctkPluginPrivate::update0(const QUrl& updateLocation, bool wasActive)
   }
   catch (const std::exception& e)
   {
-    if (newArchive != 0)
+    if (!newArchive.isNull())
     {
       newArchive->purge();
     }
@@ -549,7 +548,7 @@ void ctkPluginPrivate::update0(const QUrl& updateLocation, bool wasActive)
   // TODO: check if dependent plug-ins are started. If not, set purgeOld to true.
 
   // Activate new plug-in
-  ctkPluginArchive* oldArchive = archive;
+  QSharedPointer<ctkPluginArchive> oldArchive = archive;
   archive = newArchive;
   cachedRawHeaders.clear();
   state = ctkPlugin::INSTALLED;

+ 2 - 2
Libs/PluginFramework/ctkPluginPrivate_p.h

@@ -93,7 +93,7 @@ public:
    * @exception std::invalid_argument Faulty manifest for bundle
    */
   ctkPluginPrivate(QWeakPointer<ctkPlugin> qq, ctkPluginFrameworkContext* fw,
-                   ctkPluginArchive* pa /*, Object checkContext*/);
+                   QSharedPointer<ctkPluginArchive> pa /*, Object checkContext*/);
 
   /**
    * Construct a new empty ctkPlugin.
@@ -223,7 +223,7 @@ public:
   /**
    * ctkPlugin archive
    */
-  ctkPluginArchive* archive;
+  QSharedPointer<ctkPluginArchive> archive;
 
   /**
    * Directory for plugin data

+ 52 - 35
Libs/PluginFramework/ctkPluginStorageSQL.cpp

@@ -259,7 +259,7 @@ void ctkPluginStorageSQL::updateDB()
                       "FROM " PLUGINS_TABLE " GROUP BY ID";
 
   QList<int> outdatedIds;
-  QList<ctkPluginArchiveSQL*> updatedPluginArchives;
+  QList<QSharedPointer<ctkPluginArchiveSQL> > updatedPluginArchives;
   try
   {
     executeQuery(&query, statement);
@@ -275,14 +275,15 @@ void ctkPluginStorageSQL::updateDB()
 
       if (pluginLastModified > getQDateTimeFromString(query.value(EBindIndex4).toString()))
       {
-        ctkPluginArchiveSQL* updatedPA =
-            new ctkPluginArchiveSQL(this,
-                                    query.value(EBindIndex2).toUrl(),    // plug-in location url
-                                    query.value(EBindIndex3).toString(), // plugin local path
-                                    query.value(EBindIndex).toInt(),     // plugin id
-                                    query.value(EBindIndex5).toInt(),    // start level
-                                    QDateTime(),                         // last modififed
-                                    query.value(EBindIndex6).toInt());   // auto start setting
+        QSharedPointer<ctkPluginArchiveSQL> updatedPA(
+              new ctkPluginArchiveSQL(this,
+                                      query.value(EBindIndex2).toUrl(),    // plug-in location url
+                                      query.value(EBindIndex3).toString(), // plugin local path
+                                      query.value(EBindIndex).toInt(),     // plugin id
+                                      query.value(EBindIndex5).toInt(),    // start level
+                                      QDateTime(),                         // last modififed
+                                      query.value(EBindIndex6).toInt())    // auto start setting
+              );
         updatedPA->key = query.value(EBindIndex7).toInt();
         updatedPluginArchives << updatedPA;
 
@@ -329,7 +330,7 @@ void ctkPluginStorageSQL::updateDB()
 
     try
     {
-      foreach (ctkPluginArchiveSQL* updatedPA, updatedPluginArchives)
+      foreach (QSharedPointer<ctkPluginArchiveSQL> updatedPA, updatedPluginArchives)
       {
         insertArchive(updatedPA, &query);
       }
@@ -359,7 +360,7 @@ QLibrary::LoadHints ctkPluginStorageSQL::getPluginLoadHints() const
 }
 
 //----------------------------------------------------------------------------
-ctkPluginArchive* ctkPluginStorageSQL::insertPlugin(const QUrl& location, const QString& localPath)
+QSharedPointer<ctkPluginArchive> ctkPluginStorageSQL::insertPlugin(const QUrl& location, const QString& localPath)
 {
   QMutexLocker lock(&m_archivesLock);
 
@@ -371,8 +372,8 @@ ctkPluginArchive* ctkPluginStorageSQL::insertPlugin(const QUrl& location, const
 
   const QString libTimestamp = getStringFromQDateTime(fileInfo.lastModified());
 
-  ctkPluginArchiveSQL* archive = new ctkPluginArchiveSQL(this, location, localPath,
-                                                         m_nextFreeId++);
+  QSharedPointer<ctkPluginArchiveSQL> archive(new ctkPluginArchiveSQL(this, location, localPath,
+                                                                      m_nextFreeId++));
   try
   {
     insertArchive(archive);
@@ -381,15 +382,13 @@ ctkPluginArchive* ctkPluginStorageSQL::insertPlugin(const QUrl& location, const
   }
   catch(...)
   {
-    delete archive;
     m_nextFreeId--;
     throw;
   }
-  return 0;
 }
 
 //----------------------------------------------------------------------------
-void ctkPluginStorageSQL::insertArchive(ctkPluginArchiveSQL* pa)
+void ctkPluginStorageSQL::insertArchive(QSharedPointer<ctkPluginArchiveSQL> pa)
 {
   checkConnection();
 
@@ -412,7 +411,7 @@ void ctkPluginStorageSQL::insertArchive(ctkPluginArchiveSQL* pa)
 }
 
 //----------------------------------------------------------------------------
-void ctkPluginStorageSQL::insertArchive(ctkPluginArchiveSQL* pa, QSqlQuery* query)
+void ctkPluginStorageSQL::insertArchive(QSharedPointer<ctkPluginArchiveSQL> pa, QSqlQuery* query)
 {
 
   QFileInfo fileInfo(pa->getLibLocation());
@@ -495,19 +494,19 @@ void ctkPluginStorageSQL::insertArchive(ctkPluginArchiveSQL* pa, QSqlQuery* quer
 }
 
 //----------------------------------------------------------------------------
-ctkPluginArchive* ctkPluginStorageSQL::updatePluginArchive(ctkPluginArchive* old,
+QSharedPointer<ctkPluginArchive> ctkPluginStorageSQL::updatePluginArchive(QSharedPointer<ctkPluginArchive> old,
                                                            const QUrl& updateLocation,
                                                            const QString& localPath)
 {
-  ctkPluginArchiveSQL* newPA = new ctkPluginArchiveSQL(
-                                 static_cast<ctkPluginArchiveSQL*>(old),
-                                 m_generations[old->getPluginId()]++,
-                                 updateLocation, localPath);
+  QSharedPointer<ctkPluginArchive> newPA(new ctkPluginArchiveSQL(
+                                           qSharedPointerCast<ctkPluginArchiveSQL>(old),
+                                           m_generations[old->getPluginId()]++,
+                                           updateLocation, localPath)
+                                         );
   return newPA;
-
 }
 
-void ctkPluginStorageSQL::replacePluginArchive(ctkPluginArchive *oldPA, ctkPluginArchive *newPA)
+void ctkPluginStorageSQL::replacePluginArchive(QSharedPointer<ctkPluginArchive> oldPA, QSharedPointer<ctkPluginArchive> newPA)
 {
   QMutexLocker lock(&m_archivesLock);
 
@@ -528,8 +527,8 @@ void ctkPluginStorageSQL::replacePluginArchive(ctkPluginArchive *oldPA, ctkPlugi
 
   try
   {
-    removeArchiveFromDB(static_cast<ctkPluginArchiveSQL*>(oldPA), &query);
-    insertArchive(static_cast<ctkPluginArchiveSQL*>(newPA), &query);
+    removeArchiveFromDB(static_cast<ctkPluginArchiveSQL*>(oldPA.data()), &query);
+    insertArchive(qSharedPointerCast<ctkPluginArchiveSQL>(newPA), &query);
 
     commitTransaction(&query);
     m_archives[pos] = newPA;
@@ -548,7 +547,7 @@ void ctkPluginStorageSQL::replacePluginArchive(ctkPluginArchive *oldPA, ctkPlugi
 }
 
 //----------------------------------------------------------------------------
-bool ctkPluginStorageSQL::removeArchive(ctkPluginArchive *pa)
+bool ctkPluginStorageSQL::removeArchive(ctkPluginArchiveSQL* pa)
 {
   checkConnection();
 
@@ -559,11 +558,15 @@ bool ctkPluginStorageSQL::removeArchive(ctkPluginArchive *pa)
 
   try
   {
-    removeArchiveFromDB(static_cast<ctkPluginArchiveSQL*>(pa), &query);
+    removeArchiveFromDB(pa, &query);
     commitTransaction(&query);
 
     QMutexLocker lock(&m_archivesLock);
-    m_archives.removeAll(pa);
+    int idx = find(pa);
+    if (idx >= 0 && idx < m_archives.size())
+    {
+      m_archives.removeAt(idx);
+    }
     return true;
   }
   catch (const ctkRuntimeException& re)
@@ -580,6 +583,12 @@ bool ctkPluginStorageSQL::removeArchive(ctkPluginArchive *pa)
 }
 
 //----------------------------------------------------------------------------
+bool ctkPluginStorageSQL::removeArchive(QSharedPointer<ctkPluginArchive> pa)
+{
+  return removeArchive(static_cast<ctkPluginArchiveSQL*>(pa.data()));
+}
+
+//----------------------------------------------------------------------------
 void ctkPluginStorageSQL::removeArchiveFromDB(ctkPluginArchiveSQL* pa, QSqlQuery* query)
 {
   QString statement = "DELETE FROM " PLUGINS_TABLE " WHERE K=?";
@@ -590,7 +599,7 @@ void ctkPluginStorageSQL::removeArchiveFromDB(ctkPluginArchiveSQL* pa, QSqlQuery
   executeQuery(query, statement, bindValues);
 }
 
-QList<ctkPluginArchive*> ctkPluginStorageSQL::getAllPluginArchives() const
+QList<QSharedPointer<ctkPluginArchive> > ctkPluginStorageSQL::getAllPluginArchives() const
 {
   return m_archives;
 }
@@ -598,10 +607,8 @@ QList<ctkPluginArchive*> ctkPluginStorageSQL::getAllPluginArchives() const
 QList<QString> ctkPluginStorageSQL::getStartOnLaunchPlugins() const
 {
   QList<QString> res;
-  QListIterator<ctkPluginArchive*> i(m_archives);
-  while(i.hasNext())
+  foreach(QSharedPointer<ctkPluginArchive> pa, m_archives)
   {
-    ctkPluginArchive* pa = i.next();
     if (pa->getAutostartSetting() != -1)
     {
       res.push_back(pa->getPluginLocation().toString());
@@ -975,6 +982,16 @@ int ctkPluginStorageSQL::find(long id) const
 }
 
 //----------------------------------------------------------------------------
+int ctkPluginStorageSQL::find(ctkPluginArchive *pa) const
+{
+  for (int i = 0; i < m_archives.size(); ++i)
+  {
+    if (m_archives[i].data() == pa) return i;
+  }
+  return -1;
+}
+
+//----------------------------------------------------------------------------
 void ctkPluginStorageSQL::checkConnection() const
 {
   if(!m_isDatabaseOpen)
@@ -1074,8 +1091,8 @@ void ctkPluginStorageSQL::restorePluginArchives()
 
     try
     {
-      ctkPluginArchiveSQL* pa = new ctkPluginArchiveSQL(this, location, localPath, id,
-                                                        startLevel, lastModified, autoStart);
+      QSharedPointer<ctkPluginArchiveSQL> pa(new ctkPluginArchiveSQL(this, location, localPath, id,
+                                                                     startLevel, lastModified, autoStart));
       pa->key = query.value(EBindIndex6).toInt();
       pa->readManifest();
       m_archives.append(pa);

+ 28 - 11
Libs/PluginFramework/ctkPluginStorageSQL_p.h

@@ -59,7 +59,7 @@ public:
    *
    * @throws ctkPluginDatabaseException
    */
-  ctkPluginArchive* insertPlugin(const QUrl& location, const QString& localPath);
+  QSharedPointer<ctkPluginArchive> insertPlugin(const QUrl& location, const QString& localPath);
 
   /**
    * Insert a new plugin (shared library) into the persistent
@@ -71,7 +71,8 @@ public:
    * @param localPath Path to a plugin on the local file system.
    * @return Plugin archive object.
    */
-  ctkPluginArchive* updatePluginArchive(ctkPluginArchive* old, const QUrl& updateLocation, const QString& localPath);
+  QSharedPointer<ctkPluginArchive> updatePluginArchive(QSharedPointer<ctkPluginArchive> old,
+                                                       const QUrl& updateLocation, const QString& localPath);
 
   /**
    * Replace old plugin archive with a new updated plugin archive, that
@@ -80,21 +81,21 @@ public:
    * @param oldPA ctkPluginArchive to be replaced.
    * @param newPA new ctkPluginArchive.
    */
-  void replacePluginArchive(ctkPluginArchive* oldPA, ctkPluginArchive* newPA);
+  void replacePluginArchive(QSharedPointer<ctkPluginArchive> oldPA, QSharedPointer<ctkPluginArchive> newPA);
 
   /**
    * Removes all persisted data related to the given ctkPluginArchive.
    *
    * @throws ctkPluginDatabaseException
    */
-  bool removeArchive(ctkPluginArchive* pa);
+  bool removeArchive(QSharedPointer<ctkPluginArchive> pa);
 
   /**
    * Get all plugin archive objects.
    *
    * @return QList of all PluginArchives.
    */
-  QList<ctkPluginArchive*> getAllPluginArchives() const;
+  QList<QSharedPointer<ctkPluginArchive> > getAllPluginArchives() const;
 
   /**
    * Get all plugins to start at next launch of framework.
@@ -174,6 +175,14 @@ public:
    */
   void setAutostartSetting(int key, int autostart);
 
+  /**
+   * Removes all persisted data related to the given ctkPluginArchiveSQL.
+   * This is identical to removeArchive(QSharedPointer<ctkPluginArchive>).
+   *
+   * @throws ctkPluginDatabaseException
+   */
+  bool removeArchive(ctkPluginArchiveSQL* pa);
+
 private:
 
   enum TransactionType{Read, Write};
@@ -196,13 +205,21 @@ private:
   bool isOpen() const;
 
   /**
-   * Find posisition for BundleArchive with specified id
+   * Find position for ctkPluginArchive with specified id
    *
-   * @param id Bundle archive id to find.
-   * @return String to write
+   * @param id Plugin archive id to find.
+   * @return Position in the m_archives List.
    */
   int find(long id) const;
 
+  /**
+   * Find position for ctkPluginArchive
+   *
+   * @param id Plugin archive id to find.
+   * @return Position in the m_archives List.
+   */
+  int find(ctkPluginArchive* pa) const;
+
   void initNextFreeIds();
 
   /**
@@ -255,9 +272,9 @@ private:
    */
   void updateDB();
 
-  void insertArchive(ctkPluginArchiveSQL *pa);
+  void insertArchive(QSharedPointer<ctkPluginArchiveSQL> pa);
 
-  void insertArchive(ctkPluginArchiveSQL *pa, QSqlQuery* query);
+  void insertArchive(QSharedPointer<ctkPluginArchiveSQL> pa, QSqlQuery* query);
 
   void removeArchiveFromDB(ctkPluginArchiveSQL *pa, QSqlQuery *query);
 
@@ -316,7 +333,7 @@ private:
   /**
    * Plugin id sorted list of all active plugin archives.
    */
-  QList<ctkPluginArchive*> m_archives;
+  QList<QSharedPointer<ctkPluginArchive> > m_archives;
 
   /**
    * Framework handle.

+ 7 - 5
Libs/PluginFramework/ctkPluginStorage_p.h

@@ -24,6 +24,7 @@
 
 #include <QUrl>
 #include <QStringList>
+#include <QSharedPointer>
 
 // CTK class forward declarations
 class ctkPluginArchive;
@@ -47,7 +48,7 @@ public:
    * @param localPath Path to the plugin on the local file system
    * @return Plugin archive object.
    */
-  virtual ctkPluginArchive* insertPlugin(const QUrl& location, const QString& localPath) = 0;
+  virtual QSharedPointer<ctkPluginArchive> insertPlugin(const QUrl& location, const QString& localPath) = 0;
 
   /**
    * Insert a new plugin (shared library) into the persistent
@@ -60,7 +61,8 @@ public:
    * @param localPath Path to a plugin on the local file system.
    * @return Plugin archive object.
    */
-  virtual ctkPluginArchive* updatePluginArchive(ctkPluginArchive* old, const QUrl& updateLocation, const QString& localPath) = 0;
+  virtual QSharedPointer<ctkPluginArchive> updatePluginArchive(QSharedPointer<ctkPluginArchive> old,
+                                                               const QUrl& updateLocation, const QString& localPath) = 0;
 
   /**
    * Replace old plugin archive with a new updated plugin archive, that
@@ -69,7 +71,7 @@ public:
    * @param oldPA ctkPluginArchive to be replaced.
    * @param newPA new ctkPluginArchive.
    */
-  virtual void replacePluginArchive(ctkPluginArchive* oldPA, ctkPluginArchive* newPA) = 0;
+  virtual void replacePluginArchive(QSharedPointer<ctkPluginArchive> oldPA, QSharedPointer<ctkPluginArchive> newPA) = 0;
 
   /**
    * Remove plugin archive from archives list and persistent storage.
@@ -79,14 +81,14 @@ public:
    * @param pa Plugin archive to remove.
    * @return true if element was removed.
    */
-  virtual bool removeArchive(ctkPluginArchive* pa) = 0;
+  virtual bool removeArchive(QSharedPointer<ctkPluginArchive> pa) = 0;
 
   /**
    * Get all plugin archive objects.
    *
    * @return QList of all PluginArchives.
    */
-  virtual QList<ctkPluginArchive*> getAllPluginArchives() const = 0;
+  virtual QList<QSharedPointer<ctkPluginArchive> > getAllPluginArchives() const = 0;
 
   /**
    * Get all plugins to start at next launch of framework.

+ 5 - 5
Libs/PluginFramework/ctkPlugins.cpp

@@ -72,7 +72,7 @@ QSharedPointer<ctkPlugin> ctkPlugins::install(const QUrl& location, QIODevice* i
     }
 
     // install new plugin
-    ctkPluginArchive* pa = 0;
+    QSharedPointer<ctkPluginArchive> pa;
     QString localPluginPath;
     try
     {
@@ -125,7 +125,7 @@ QSharedPointer<ctkPlugin> ctkPlugins::install(const QUrl& location, QIODevice* i
     }
     catch (const std::exception& e)
     {
-      if (pa)
+      if (!pa.isNull())
       {
         pa->purge();
       }
@@ -288,14 +288,14 @@ QList<QSharedPointer<ctkPlugin> > ctkPlugins::getActivePlugins() const
 //----------------------------------------------------------------------------
 void ctkPlugins::load()
 {
-  QList<ctkPluginArchive*> pas = fwCtx->storage->getAllPluginArchives();
-  QListIterator<ctkPluginArchive*> it(pas);
+  QList<QSharedPointer<ctkPluginArchive> > pas = fwCtx->storage->getAllPluginArchives();
+  QListIterator<QSharedPointer<ctkPluginArchive> > it(pas);
 
   {
     QMutexLocker lock(&objectLock);
     while (it.hasNext())
     {
-      ctkPluginArchive* pa = it.next();
+      QSharedPointer<ctkPluginArchive> pa = it.next();
       try
       {
         QSharedPointer<ctkPlugin> plugin(new ctkPlugin());