I have an application consisting of an executable and several DLLs.
The exe links a dll statically. This dll creates a worker thread which instantiates a Q_GLOBAL_STATIC object (first access). So this object (derived from QObject) lives in this worker thread.
At program exit this object needs to be destroyed in the worker thread. But it is actually destroyed when the static dll gets unloaded, which is happening in the main thread.
How do I delete this global static object in the correct thread?
I tried manually deleting it when my worker thread finishes. But this results in a crash after my destructor returns.
CodePudding user response:
You need to explicit call destructor on that object like this obj.~Test();
then after check if object is destroyed obj.isDestroyed()
if it is not working.
Use QLibrary to load and unload dll ( https://doc.qt.io/archives/qt-4.8/qlibrary.html). Where in Q_GLOBAL_STATIC
documentation(https://doc.qt.io/qt-5/qglobalstatic.html#destruction) it is mention that destructor will be called on unload of library or atexit() funciton of application.
CodePudding user response:
I'd like to share my solution. To make it work, I introduced a simple private class which I use as a QGlobalStatic. This global object of this class holds the real singleton object and allows safe deletion of it in the correct thread.
The header file:
class MySingletonPrivate;
class MySingleton : public QObject
{
Q_OBJECT
public:
static MySingleton* instance();
static void deleteInstance();
protected:
MySingleton( QObject *parent = nullptr );
~MySingleton();
friend class MySingletonPrivate;
};
The cpp file:
class MySingletonPrivate
{
public:
MySingletonPrivate()
: inst( new MySingleton() )
{
QObject::connect( QThread::currentThread(), &QThread::finished, inst, &MySingleton::deleteLater );
}
~MySingletonPrivate()
{
Q_ASSERT( inst.isNull() );
}
MySingleton* instance() const
{
return inst;
}
private:
QPointer< MySingleton > inst;
};
Q_GLOBAL_STATIC( MySingletonPrivate, s_instance );
MySingleton* MySingleton::instance()
{
return s_instance->instance();
}
void MySingleton::deleteInstance()
{
delete s_instance->instance();
}
Using the signal QThread::finished the global instance is deleted at the end of the worker thread. I left out the include instructions and the constructor and destructor implemention to make the answer shorter. Of course, the first call to MySingleton::instance() must happen in the worker thread.