Deleting object that inherits from QWidget, WA_DeleteOnClose segmentation fault - c++

I'm using an object the inherits QWidget, and in order to know when it is closed, I've used setAttribute(Qt::WA_DeleteOnClose), and connected
connect(myObj,SIGNAL(destroyed(QObject*)),this,SLOT(handleFinish()));
However, when the object is being deleted, I get munmap_chunk(): invalid pointer, and when I look at the address of the pointer, it is one of the data members of myObj, which is really not a pointer.
I allocate myObj dynamically, so it is supposed to be on the heap - myObj = new myObj();
The error comes at the end of myObj destructor, and I've checked that this is the first time the destructor is called (after looking at When setting the WA_DeleteOnClose attribute on a Qt MainWindow, the program crashes when deleting the ui pointer).
Any suggestions for dealing with it?

By the time you receive the destroyed signal, the object is only a QObject - not a QWidget and definitely not of any derived type. You can only access the members and methods provided via QObject, not via any other type.
It seems that you wish to be notified when a widget is about to close: for that, install an event filter that intercepts QEvent::close on the widget. See also this answer and a discussion of why a closeEvent cannot be generally handled via a slot.

Related

How to safely use QQmlEngine::CppOwnership?

When calling C++ from QML, a QObject can be returned to qml by pointer. Before returning, I can call
QObject* qobj = m_sharedPtr.data(); // Pointer to member shared-ptr-managed object.
QQmlEngine::setObjectOwnership(qobj, QQmlEngine::CppOwnership);
return qobj;
but given that QML is garbage-collected, how can this work safely? My mental model is that QML will get the pointer and hold onto it, wrapped in some QML pointer wrapper and that pointer wrapper will eventually be GC'd. But then there's no limit to how long after the setObjectOwnership call that QML could access *qobj. (E.g., perhaps the next QML->C++ call after this one causes m_sharedPtr to go out of scope.) Does that mean QQmlEngine::CppOwnership is only safe to use when the object's lifetime is essentially infinite (e.g., a singleton)? I don't see any alternative, but haven't found any mention of this issue in any documentation.
If m_sharedPtr refers to data created in C++, qobj will have CppOwnership anyways, and you should handle it like any other C++ smart pointer (i.e. let it live as long as you actually need it).
If it was created in QML, it will have JavaScriptOwnership by default. If you then transfer ownership to C++, and it gets destroyed, it's not accessible in QML anymore.
If it is important that qobj is accessible in QML for an uncertain time, but still C++-managed, you could retreat to using raw pointers and handle the destruction yourself (e.g. by connecting to the aboutToClose() signal of a QML window).

Should destructor be called on member objects [duplicate]

This question already has answers here:
Do I have to delete it? [Qt]
(3 answers)
Closed 4 years ago.
When looking at Qt examples (on Qt documentation like movieplayer example, or here), I never see the member destructors explicitly called.
A class definition is like:
class foo : public QParent {
Q_OBJECT
QStuff stuff;
foo (QWidget *parent) : QParent(parent)
{
stuff = new QStuff(this);
}
};
My problem is that I never see something like delete stuff;
So my questions are:
Are QObject derived class instances which parent is not NULL automatically deleted when their parent is?
Is it dangerous to delete a QObject derived member without setting it to NULL?
I guess the answers are Yes and No, but I'm not sure.
For the first question yes. You can check the Qt docs here
where it is stated clearly:
QObjects organize themselves in object trees. When you create a
QObject with another object as parent, the object will automatically
add itself to the parent's children() list. The parent takes ownership
of the object; i.e., it will automatically delete its children in its
destructor. You can look for an object by name and optionally type
using findChild() or findChildren().
For the second question, the answer deserves a little bit more of explanation. If you have QObject pointers members that are not children of your object, you have to handle their disposal manually in the destructor of your class.
You can in theory use delete on any QObject* to invoke its destructor, but since Qt objects have a powerfull event system based on signals/slots, you must be aware of the interactions with event loops. If you brutally delete a QObject connected to another QObject while the latter one is still processing a signal coming from the first one, you may end up with some problems.
This holds in both mono and multi-threaded applications. You should therefore avoid the use of delete in favor of QObject::deleteLater() that will defer the deletion of the QObject until all the signal/slots related to it have been processed.
Lastly, in the context of the implementation of a destructor it doesn't really matter if you set the pointer to null, because it will be unavailable for further use anyway. It may be important if you delete the pointee in some other method, while your instance is still alive, and you set the pointer to null to flag it as uninitialized.
No, you do not need to delete member objects. They will get destroyed automatically when the parent class object gets destroyed.
See this FAQ.
In the case of Qt QObject pointer members, then the parent is the owner and is responsible for deleting the QObject. See here.

Qt - How a QObject with a parent on the stack might get deleted twice?

Can someone explain the following please?
Stack or Heap?
In general, a QObject without a parent should be created on the stack or defined as an subobject of another class. A QObject with a parent should not be on the stack because then it might get deleted twice accidentally. All QObjects created on the heap should either have a parent, or be managed somehow by another object.
Source: LINK
Sorry, downvoting the accepted answer. Both versions as currently explained are wrong, and especially the conclusion is very wrong.
Parent/child for memory management
Amongst other things, Qt uses the parent/child concept to manage memory. When an object is parented to another one, then
deleting the parent will also delete (via operator delete) all of its children. Of course, this works recursively;
deleting a child will un-parent it, so that the parent will not attempt a double deletion. deleteLater is not required for this to work -- any deletion will un-parent it.
This allows you to build a tree of QObjects via repeated dynamic allocations through operator new, and not having the problem of having to manually delete all the allocated objects. Just give them parents, and you'll only have to delete the root of the tree. You can also delete a child (i.e. a subtree) at any time, and that will do the right thing™.
In the end, you will have no leaks and no double deletions.
This is why in constructors you'll see things like:
class MyWidget : public QWidget // a QObject subclass
{
Q_OBJECT
public:
MyWidget(QWidget *parent = nullptr);
// default destructor is fine!
private:
// raw pointers:
// we won't own these objects through these pointers.
// we just need them to access the pointees
QTimer *m_timer;
QPushButton *m_button;
};
void MyWidget::MyWidget(QWidget *parent) : QWidget(parent)
{
// don't need to save the pointer to this child. because reasons
auto lineEdit = new QLineEdit(this);
auto validator = new QIntValidator(lineEdit); // a nephew
// but let's save the pointers to these children
m_timer = new QTimer(this);
m_button = new QPushButton(this);
// ...
}
The default destructor will properly delete the entire tree, although we allocated the children objects through calls to operator new, and we didn't even bother to save in members the pointers to some children.
QObjects on the stack
You are allowed (and in certain contexts it's actually a good idea) to give parents to objects allocated on the stack.
The typical example is of QDialog subclasses:
void MyWidget::showOptionsDialog()
{
// OptionsDialog is a QDialog subclass;
// create an instance as a child of "this" object
OptionsDialog d(this);
// exec the dialog (i.e. show it as a modal dialog)
conts auto result = d.exec();
if (result == QDialog::Accept) {
// apply the options
}
// d gets destroyed here
// => it will remove itself as a child of this
}
The purpose of passing this as the dialog's parent is to allow the dialog to be centered upon the parent's widget, share the task tray entry, and be modal against it. This is explained in QDialog docs. Also, ultimately, d does only need to live in that function, so it's a good idea to declare it as an automatic variable (i.e. allocated on the stack).
There you go: you've got a QObject, allocated on the stack, with a parent.
So what's the danger of QObjects on the stack? Consider this code:
QObject *parent = new QObject;
QObject child(parent);
delete parent;
As explained before, parent here will attempt to call operator delete on child, an object which was not allocated using new (it's on the stack). That's illegal (and a likely crash).
Obviously, nobody writes code like this, but consider the dialog example above again. What if, during the call d.exec(), we manage somehow to delete this, that is, the dialog's parent? That could happen for a variety of reasons very, very difficult to track down -- for instance, data arrives on a socket which causes widgets in your UI to change, creating some and destroying others. Ultimately, you would delete a stack variable, crashing (and having an extremely hard time trying to reproduce the crash).
Hence the suggestion to avoid creating code like that in the first place. It's not illegal, it may work, but it may also not work, and nobody likes fragile code.

Can Qt arrange for QObject* to be set to nullptr when QObject is destroyed?

Qt framework has an signal for all QObjects which is emmited before destruction of that QObject. This event can be used to have some QObject* variable automatically emptied when the object it points to is destroyed.
But to do this, you need to employ relatively lot of code. You would need to register a signal and link it up to the variable. Not very convenient in my opinion.
Can I have it arranged (by Qt) that a pointer to QObject is cleared automatically when QObject is destroyed?
Not with a raw pointer, no, but Qt supplies a templated QPointer class that does exactly what you are describing.

how are QActions deleted

I am pretty confused about one thing in Qt:
You often add new actions to QMenu like this:
menu.addAction(new QAction("this is a menu"));
so you are creating a new object but who is deleting it? According to https://qt-project.org/forums/viewthread/25717 the parent object should take care of that but... does it always happen? What if I didn't put any parent object in constructor? What if I deleted the object myself, will parent object SEGFAULT as it deletes object that was already deleted?
Even default code that is created by qt creator is creating object called ui in constructor and deletes it in destructor. That is what I was doing for my own objects that I created on the fly, but surprisingly, it never crashed. I just figured out that all the time I probably shouldn't have even delete them myself?
What is a proper way to deal with this? Does it apply for all QObjects that had a pointer to parent object in constructor?
Bonus question: if these objects are deleted by parent's destructor, does it mean that if parent is main window of application that is closed on exit only, that all new objects will just leak until the application is closed?
If you want a QObject to be automatically deleted, you must specify a parent. Most derived classes provide for this in one or more of their constructor parameters.
The QAction you created above does not have a parent so it will not be deleted when the QMenu is destroyed. To make it do so, change the line to be:
menu.addAction(new QAction("this is a menu", &menu));
This is not advisable though since QAction is an implementation of the command pattern so it is intended to be used in more places than a QMenu and thus its lifespan must not be tied to that of the QMenu. A simple example would be as a button on a QToolBar.
For this reason, the QMenu does not make itself the parent of the QAction when you add it.
Some other derived classes of QObject do indeed do this so it is not always necessary to explicitly assign a parent yourself.
One common example is QMainWindow. Whenever you assign a QWidget using setCentralWidget(), the main window will take ownership and force itself to be the parent of the new central widget, even if you made some other object that widget's parent.