DeleteLater works... but why?
I have been debugging a multi-threaded application for a while now.
Recently I had been getting Heap corruption breakpoints from VS .net and had been trying to locate the source.
I found the source in a widget that deleted another widget directly. Apparently some part of the code was still pointing to it after i deleted it. (It wasn't any of my written code, but it may have been Qt or MS generated)
Anyway, on a hunch i tried deleteLater for the sub-widget, and it worked like a charm. (No more heap corruption errors at any rate)
I am wondering if there is any reason deleting a widget directly is bad in a multi-threaded application?
(Can't post any of my code as it does not belong to me. It belongs to my company)
Re: DeleteLater works... but why?
A QObject automatically deletes all its children when itself is deleted.
So, I assume that after you deleted that widget, and it deleted it's children, there remained some references throughout the app to the invalid children.
Therefore it does not matter that the app is multithreaded or not.
Why not "deleteLater" the parent widget?
Regards
Re: DeleteLater works... but why?
Did you try to delete the object from within a slot that took it as an argument?
Re: DeleteLater works... but why?
I should explain more specifically:
I am placing a new Widget pointer (call it widgetA) in a struct-like QObject class. (all data members public)
That widgetA performs a function, sends a signal to the struct-like Qobject's creator, who then deletes the widgetA and the struct-like widget.
The signal being received is a unique variable to that object that allows me to search a list for the object while under the protection of a mutex locker.
In this case the VS .NET would complain on the very next new memory allocation about a heap corruption.
If I use deleteLater on the widgetA and then also on the struct-like Qobject, it no longer has this issue.
Re: DeleteLater works... but why?
Could you please answer my question?
Re: DeleteLater works... but why?
Quote:
Originally Posted by
TheGrimace
The signal being received is a unique variable to that object that allows me to search a list for the object while under the protection of a mutex locker.
As I said, I am receiving a unique variable (in this case an integer) so the answer to your question is no.
Re: DeleteLater works... but why?
But you receive from where? Maybe in the chain of calls the object that gets deleted in one of "subslots" is passed as a signal parameter at some point?
Re: DeleteLater works... but why?
I never pass any objects by reference in this particular case.
I receive the signal emitted from widgetA into the object that deletes it. The signal contains a unique integer passed by value. I believe Qt::AutoConnection turns the connection into a direct connection.
Re: DeleteLater works... but why?
Let me explain... Imagine we have a following situation:
Code:
//...
signals:
};
//...
signals:
void sigB(int);
public slots:
void slotB
(QObject *o
){ emit sigB
(m_list.
indexOf(o
));
} };
//...
public slots:
};
Now imagine we connect sigA to slotB and slotC and sigB to some slot that deletes the item pointed by the integer emited from sigB. If sigA is emitted, slotB is called and emits sigB which in turn calls a slot that deletes the item. Seems fine... But then slotC is called and tries to operate on the same object. But it has already been deleted! Hence the crash. Now if you use deleteLater(), the object is deleted only after all slot have been called. That's probably the problem you're facing, but I can't be sure without seeing your code.
Re: DeleteLater works... but why?
Would I get the same same result if the instance of A&C were inside of B?
IE
A&C -> signals -> B
B -> signals -> D (the object that created B) to delete it.
but A and C are new instances of those classes created in B.
kind of like:
Code:
//...
signals:
//...
B() { a= new A(); b=new B(); connect(AtoB); connect(CtoB);}
signals:
void sigB(int);
public slots:
void slotB
(QObject *o
){ emit sigB
(m_list.
indexOf(o
));
} };
//...
public slots:
};
//...
public:
D() { b = new B(); connect(B to D);}
public slots:
DSlot() { delete b or deletelater b}
};
and B initiates a call to the D Slot which deletes it and its children.
Re: DeleteLater works... but why?
The relationship doesn't matter. The only thing that matters is that more than one slot operates on the same object that gets deleted in one of the slots. If that is the case, you have to use deleteLater() or somehow check if the pointer is stil valid (checking for null won't do).
Re: DeleteLater works... but why?
That is most likely what was going wrong then.
Thank You for your help.