[Qt-interest] Crash in QAbstractTableModel.beginRemoveRows

Scott Aron Bloom Scott.Bloom at onshorecs.com
Sat Dec 11 00:42:08 CET 2010



-----Original Message-----
From: qt-interest-bounces at trolltech.com
[mailto:qt-interest-bounces at trolltech.com] On Behalf Of Stephen Kelly
Sent: Friday, December 10, 2010 3:20 PM
To: qt-interest at trolltech.com
Subject: Re: [Qt-interest] Crash in QAbstractTableModel.beginRemoveRows

Scott Aron Bloom wrote:

>> Hi
>> 
>> I have implemented an Model/View, where the Model runs in it's on
> thread.
>> With a sample interval of 500ms it collects data an writes to a ring
>> buffer stored in a file.
>> After inserting a new record to the full ring buffer I call:
>> 
>> beginInsertRows ( QModelIndex(), m_Index.lineCount(),
>> m_Index.lineCount()); endInsertRows();
>> beginRemoveRows ( QModelIndex(), 0, 0);
>> endRemoveRows();
>> 
>> This is not very elegant, but I to now a better(:
>> Any better solution?
>> 
>> The application, after while, crashes in:
>> QtCored4.dll!QHashData::nextNode(QHashData::Node * node=0x00fa8b70)
>> QtCored4.dll!QHash<QModelIndex,QPersistentModelIndexData
>> *>::const_iterator::operator++()
>> QtCored4.dll!QAbstractItemModelPrivate::rowsAboutToBeRemoved(const
>> QModelIndex & parent={...}, int first=0, int last=0)
>> QtCored4.dll!QAbstractItemModel::beginRemoveRows(const QModelIndex &
>> parent={...}, int first=0, int last=0)
>> 
>> The node data is corrupt!
>> 
>> The thread has its own event loop. I use a timer for the sample
> interval.
>> DataLogThread()
>> : m_enabled( false)
>> , m_SampleIntervalMs( 0)
>> , m_SampleTimerId( 0)
>> {
>> moveToThread( this);
>> }
>> 
>> 
>> What could be the reason for the crash? Is it threading problem?
> 
> Yes. The model must live in the same thread as the view.
> 
> ---------------------
> 
> Not true, however you must be VERY VERY careful about the
> interactions...

By the same logic, the increment method in the following class is
threadsafe 
if you're VERY VERY careful:

struct Counter
{
  void increment() { ++m_count; }
  int m_count;
};

The reason the model and anything that uses its signal/slot API (such as
a 
proxy or view) must be in the same thread is that the signals contain 
information which will not be valid if the object that emitted the
signal is 
in a different thread.

http://thread.gmane.org/gmane.comp.lib.qt.general/19070/focus=19126

Particularly, the OP posted a code snippet where a row is inserted and 
removed in close proximity to each other, so is likely hitting the
problem I 
described, which is a result of the model being in a different thread.

> 
> I have successfully put a SQL table model into its own thread, so the
> blocking sql calls were in the background.

In that case it works by chance only. Can you describe how to that with 
care?

All the best,

Steve.

> 
> Scott

With proper mutexs preventing concurrently reading or writing to the SQL
query in question.

For instance, making the writing be done on explicit calls, not on
changing the view.  I forget the call (not at my development machine)

>> beginInsertRows ( QModelIndex(), m_Index.lineCount(),
>> m_Index.lineCount()); endInsertRows();
>> beginRemoveRows ( QModelIndex(), 0, 0);
>> endRemoveRows();

Is easily fixable with a properly placed QMutexLocker..

Clearly, not all "models" can be made threadsafe.. But many of them can.

Scott




More information about the Qt-interest-old mailing list