core: add class that collects global objects to be deleted on exit

We have a prevailing problem with global QObjects defined as
static global variables. These get destructed after main()
exits, which means that the QApplication object does not
exist anymore. This more often than not leads to crashes.

In a quick search I didn't find a mechanism to register
objects for deletion with QApplication. Therefore, let's
do our own list of global objects that get destructed
before destroying the QApplication.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2022-03-12 18:30:23 +01:00 committed by Dirk Hohndel
parent 197ea2b655
commit 8577b00cb7
5 changed files with 77 additions and 0 deletions

View file

@ -57,6 +57,7 @@ SOURCES += subsurface-mobile-main.cpp \
core/gas-model.c \
core/gaspressures.c \
core/git-access.c \
core/globals.cpp \
core/liquivision.c \
core/load-git.c \
core/parse-xml.c \
@ -201,6 +202,7 @@ HEADERS += \
core/event.h \
core/extradata.h \
core/git-access.h \
core/globals.h \
core/pref.h \
core/profile.h \
core/qthelper.h \

View file

@ -105,6 +105,8 @@ set(SUBSURFACE_CORE_LIB_SRCS
gettextfromc.h
git-access.c
git-access.h
globals.cpp
globals.h
imagedownloader.cpp
imagedownloader.h
import-cobalt.c

21
core/globals.cpp Normal file
View file

@ -0,0 +1,21 @@
// SPDX-License-Identifier: GPL-2.0
#include "globals.h"
#include <vector>
static std::vector<GlobalObjectBase *> global_objects;
void register_global_internal(GlobalObjectBase *o)
{
global_objects.push_back(o);
}
void free_globals()
{
// We free the objects by hand, so that we can free them in reverse
// order of creation. AFAIK, order-of-destruction is implementantion-defined
// for std::vector<>.
for (auto it = global_objects.rbegin(); it != global_objects.rend(); ++it)
delete *it;
global_objects.clear();
}

50
core/globals.h Normal file
View file

@ -0,0 +1,50 @@
// SPDX-License-Identifier: GPL-2.0
// Collection of objects that will be deleted on application exit.
// This feature is needed because many Qt-objects crash if freed
// after the application has exited.
#ifndef GLOBALS_H
#define GLOBALS_H
#include <memory>
#include <utility>
template <typename T, class... Args>
T *make_global(Args &&...args); // construct a global object of type T.
template <typename T>
T *register_global(T *); // register an already constructed object. returns input.
void free_globals(); // call on application exit. frees all global objects.
// Implementation
// A class with a virtual destructor that will be used to destruct the objects.
struct GlobalObjectBase
{
virtual ~GlobalObjectBase() { }
};
template <typename T>
struct GlobalObject : T, GlobalObjectBase
{
using T::T; // Inherit constructor from actual object.
};
void register_global_internal(GlobalObjectBase *);
template <typename T, class... Args>
T *make_global(Args &&...args)
{
GlobalObject<T> *res = new GlobalObject<T>(std::forward<Args>(args)...);
register_global_internal(res);
return res;
}
template <typename T>
T *register_global(T *o)
{
make_global<std::unique_ptr<T>>(o);
return o;
}
#endif

View file

@ -8,6 +8,7 @@
#endif
#include "stats/statsview.h"
#include "core/globals.h"
#include "core/qt-gui.h"
#include "core/settings/qPref.h"
#include "core/ssrf.h"
@ -67,6 +68,7 @@ void exit_ui()
#ifndef SUBSURFACE_MOBILE
delete MainWindow::instance();
#endif // SUBSURFACE_MOBILE
free_globals();
free((void *)existing_filename);
}