QHash and pointers - how to clear correctly
Hello!
I have the permanent segfault when I try to manually delete pointers from my hash table.
Here is some code.
This is the class that I use as hash table value:
Code:
{
Q_OBJECT
public:
QHash <QString, QString> pattern;
};
And thats my table:
Code:
QHash <QString, CMarkupPair
*> hs_markup;
I tried many ways to delete values from here. For example:
Code:
QList<CMarkupPair *> l = hs_markup.values();
foreach (CMarkupPair *p, l)
delete p;
Or, even worse:
Code:
QList <QString> hs_markup_keys
= hs_markup.
keys();
foreach
(QString key, hs_markup_keys
) {
CMarkupPair *p = hs_markup.take (key);
delete p;
}
And when I try to "delete p", I have the segfault. My "p" is not NULL, it's ok pointer. Please help :)
Re: QHash and pointers - how to clear correctly
Post the actual output and backtrace of the program when it crashes. Chances are you have a double-free message (i.e. two values in the list point to the same object) but we can only guess. Calling delete on a null pointer is not fatal in C++ but deleting the same object twice is.
Re: QHash and pointers - how to clear correctly
Your CMarkupPair class is derived from QObject. When you create the CMarkupPair instances to insert into your hash table, do you give them a non-NULL QObject parent? If you are, then they are probably getting double-deleted - once when you do it, and then again when their parent instance is deleted. Remove your code that deletes the CMarkupPair instances and they will automatically be deleted when their parent instance is deleted.
You might also try calling p->deleteLater() instead of delete(), but again, deleting them yourself isn't necessary if they have a parent.
Re: QHash and pointers - how to clear correctly
Or just use shared pointers on parent-less objects. Or QPointer<CMarkupPair> - it will be automatically set to 'null' when the object is deleted (by parent or manually). Don't trust raw pointers, each time you declare a raw pointer, a kitten dies.
Re: QHash and pointers - how to clear correctly
How about using qDeleteAll (hs_markup);
hs_markup.clear();
:)
Re: QHash and pointers - how to clear correctly
Thanks, deleteLater() resolves the problem! And the CMarkupPair instances have no parent.
Quote:
Originally Posted by
aamer4yu
Segfault :)
Thanks to all!
deleteLater() now is my magic :)
Re: QHash and pointers - how to clear correctly
Quote:
Don't trust raw pointers, each time you declare a raw pointer, a kitten dies.
OMG. I now have an army of dead kittens on my conscience. Do they really die, or just lose one of their 9 lives?
Re: QHash and pointers - how to clear correctly
Quote:
I now have an army of dead kittens on my conscience. Do they really die, or just lose one of their 9 lives?
:D
OP: I encourage you to get used to smart pointers, you will really appreciate automated memory management. You can use "deleteLater" with shared pointers:
Code:
static void delete_markup(CMarkupPair* obj){
obj->deleteLater();
}
...
typedef QSharedPointer<CMarkupPair> CMarkupPairPtr;
QHash <QString, CMarkupPairPtr> hs_markup;
// insert:
hs_markup["key"] = CMarkupPairPtr(new CMarkupPair, delete_markup);
// clear:
hs_markup.clear(); // automatically calls deleteLater() on every object in container
Re: QHash and pointers - how to clear correctly
For deleteLater() you can even pass this without the custom deleter helper function
Code:
QSharedPointer<CMarkupPaor> qobjectPtr(new CMarkupPair, &CMarkupPairt::deleteLater);
Cheers,
_
Re: QHash and pointers - how to clear correctly
I'm sort of puzzled why, if the OP created his CMarkupPair instances without parents, simply deleting them would cause a segfault. The only way I could see this happening is if the code as posted for the CMarkupPair class was incomplete, and it also has signals and/or slots that were still connected when the instances were deleted.
If the instances truly had no other references to them except being in the container (which has no ownership or control of the lifetime of the instances it contains), why would delete() cause a crash? Are there things that happen "behind the curtain" when QObject instances are created which can be undone only during deleteLater()?
Re: QHash and pointers - how to clear correctly
Maybe it was a double-delete kind of issue, and posting two "delete" events for an object solved it - after first one is processed, another one is just removed from the event queue:
Quote:
from QObject::~QObject () docs:
(...) any pending posted events for the object are removed from the event queue.