Hello, Here is a simple plugin interface:
#ifndef PluginIFace_H #define PluginIFace_H #include <QObject> class PluginIFace { public: virtual ~PluginIFace() {} // Caller takes ownership of the returned QObject* virtual QObject* getObject() = 0; }; Q_DECLARE_INTERFACE(PluginIFace, "com.example.PluginIFace/1.0" ) #endif and a concrete plugin which returns a custom SomeObject: #ifndef MyPlugin_H #define MyPlugin_H #include "pluginiface.h" class SomeObject : public QObject { Q_OBJECT public: SomeObject(QObject *parent = 0); }; class MyPlugin : public QObject, public PluginIFace { Q_OBJECT Q_PLUGIN_METADATA(IID "com.example.PluginIFace") Q_INTERFACES(PluginIFace) public: MyPlugin(QObject *parent = 0); QObject* getObject() Q_DECL_OVERRIDE; }; #endif And its implementation: #include "myplugin.h" SomeObject::SomeObject(QObject *parent) : QObject(parent) { } MyPlugin::MyPlugin(QObject *parent) : QObject(parent) { } QObject* MyPlugin::getObject() { return new SomeObject; } And a user of the plugin: QCoreApplication app(argc, argv); QPluginLoader pl(BUILD_DIR "/libmyplugin.so"); pl.load(); With the above code, valgrind reports: HEAP SUMMARY: in use at exit: 5,380 bytes in 37 blocks total heap usage: 162 allocs, 125 frees, 22,715 bytes allocated 32 bytes in 1 blocks are still reachable in loss record 12 of 37 at 0x4C2CC70: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64- linux.so) by 0x691068F: _dlerror_run (dlerror.c:141) by 0x69100C0: dlopen@@GLIBC_2.2.5 (dlopen.c:87) by 0x515B22F: QLibraryPrivate::load_sys() (qlibrary_unix.cpp:231) by 0x515651A: QLibraryPrivate::load() (qlibrary.cpp:537) by 0x51567F5: QLibraryPrivate::loadPlugin() (qlibrary.cpp:585) by 0x514C058: QPluginLoader::load() (qpluginloader.cpp:240) by 0x400E71: main (in /home/stephen/safe/dev/playground/plugintest/build/main) 64 bytes in 1 blocks are still reachable in loss record 25 of 37 at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64- linux.so) by 0x4007E06: expand_dynamic_string_token (dl-load.c:162) by 0x4008D71: _dl_map_object (dl-load.c:2538) by 0x4014A53: dl_open_worker (dl-open.c:235) by 0x400FFF3: _dl_catch_error (dl-error.c:187) by 0x40143BA: _dl_open (dl-open.c:661) by 0x691002A: dlopen_doit (dlopen.c:66) by 0x400FFF3: _dl_catch_error (dl-error.c:187) by 0x691062C: _dlerror_run (dlerror.c:163) by 0x69100C0: dlopen@@GLIBC_2.2.5 (dlopen.c:87) by 0x515B22F: QLibraryPrivate::load_sys() (qlibrary_unix.cpp:231) by 0x515651A: QLibraryPrivate::load() (qlibrary.cpp:537) 64 bytes in 1 blocks are still reachable in loss record 26 of 37 at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64- linux.so) by 0x400BDC3: _dl_new_object (dl-object.c:165) by 0x4006783: _dl_map_object_from_fd (dl-load.c:1059) by 0x4008DFF: _dl_map_object (dl-load.c:2605) by 0x4014A53: dl_open_worker (dl-open.c:235) by 0x400FFF3: _dl_catch_error (dl-error.c:187) by 0x40143BA: _dl_open (dl-open.c:661) by 0x691002A: dlopen_doit (dlopen.c:66) by 0x400FFF3: _dl_catch_error (dl-error.c:187) by 0x691062C: _dlerror_run (dlerror.c:163) by 0x69100C0: dlopen@@GLIBC_2.2.5 (dlopen.c:87) by 0x515B22F: QLibraryPrivate::load_sys() (qlibrary_unix.cpp:231) 144 bytes in 1 blocks are still reachable in loss record 32 of 37 at 0x4C2CC70: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64- linux.so) by 0x40118A2: _dl_check_map_versions (dl-version.c:293) by 0x4014EEC: dl_open_worker (dl-open.c:278) by 0x400FFF3: _dl_catch_error (dl-error.c:187) by 0x40143BA: _dl_open (dl-open.c:661) by 0x691002A: dlopen_doit (dlopen.c:66) by 0x400FFF3: _dl_catch_error (dl-error.c:187) by 0x691062C: _dlerror_run (dlerror.c:163) by 0x69100C0: dlopen@@GLIBC_2.2.5 (dlopen.c:87) by 0x515B22F: QLibraryPrivate::load_sys() (qlibrary_unix.cpp:231) by 0x515651A: QLibraryPrivate::load() (qlibrary.cpp:537) by 0x51567F5: QLibraryPrivate::loadPlugin() (qlibrary.cpp:585) 1,232 bytes in 1 blocks are still reachable in loss record 36 of 37 at 0x4C2CC70: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64- linux.so) by 0x400BB23: _dl_new_object (dl-object.c:75) by 0x4006783: _dl_map_object_from_fd (dl-load.c:1059) by 0x4008DFF: _dl_map_object (dl-load.c:2605) by 0x4014A53: dl_open_worker (dl-open.c:235) by 0x400FFF3: _dl_catch_error (dl-error.c:187) by 0x40143BA: _dl_open (dl-open.c:661) by 0x691002A: dlopen_doit (dlopen.c:66) by 0x400FFF3: _dl_catch_error (dl-error.c:187) by 0x691062C: _dlerror_run (dlerror.c:163) by 0x69100C0: dlopen@@GLIBC_2.2.5 (dlopen.c:87) by 0x515B22F: QLibraryPrivate::load_sys() (qlibrary_unix.cpp:231) LEAK SUMMARY: definitely lost: 0 bytes in 0 blocks indirectly lost: 0 bytes in 0 blocks possibly lost: 0 bytes in 0 blocks still reachable: 1,536 bytes in 5 blocks suppressed: 3,844 bytes in 32 blocks If I add pl.unload(); below the pl.load(); in the sample code above, some of the 'still reachable' reports go away: Memcheck, a memory error detector Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info Command: ./main HEAP SUMMARY: in use at exit: 3,876 bytes in 33 blocks total heap usage: 162 allocs, 129 frees, 22,715 bytes allocated 32 bytes in 1 blocks are still reachable in loss record 12 of 33 at 0x4C2CC70: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64- linux.so) by 0x691068F: _dlerror_run (dlerror.c:141) by 0x69100C0: dlopen@@GLIBC_2.2.5 (dlopen.c:87) by 0x515B22F: QLibraryPrivate::load_sys() (qlibrary_unix.cpp:231) by 0x515651A: QLibraryPrivate::load() (qlibrary.cpp:537) by 0x51567F5: QLibraryPrivate::loadPlugin() (qlibrary.cpp:585) by 0x514C058: QPluginLoader::load() (qpluginloader.cpp:240) by 0x400ED1: main (in /home/stephen/safe/dev/playground/plugintest/build/main) LEAK SUMMARY: definitely lost: 0 bytes in 0 blocks indirectly lost: 0 bytes in 0 blocks possibly lost: 0 bytes in 0 blocks still reachable: 32 bytes in 1 blocks suppressed: 3,844 bytes in 32 blocks So, maybe we should unload() Qt plugins? However, the plugin interface contains // Caller takes ownership of the returned QObject* virtual QObject* getObject() = 0; If we do something like QCoreApplication app(argc, argv); QPluginLoader pl(BUILD_DIR "/libmyplugin.so"); pl.load(); QObject *pluginObject = qobject_cast<PluginIFace*>(pl.instance())- >getObject(); pl.unload(); delete pluginObject; Then we get a segfault because the destructor of the object pointed to by pluginObject was defined in the plugin, which was just unloaded, so the destructor doesn't exist anymore. In more complex programs, it is difficult to know whether it is safe to call pl.unload() because we might not know whether all objects created through the plugin interface have already been destroyed. So, should the guideline be: "Never call QPluginLoader::unload()", and ignore 'still reachable' reports from valgrind? Thanks, Steve. _______________________________________________ Interest mailing list Interest@qt-project.org http://lists.qt-project.org/mailman/listinfo/interest