PDA

View Full Version : ASSERT Failure in QAbstractItemModel Pure Virtual Function



Corny
22nd May 2018, 22:52
I’m pulling my hair out on this one and it’s probably something simple, but I can’t find it. I initially sub-classed QAbstractItemModel and everything seemed to work fine. I made what appeared to be unrelated changes in a different .cpp file when the program started reporting an ASSERT error. I believe I changed everything back, to the state it was in when it was working properly and yet it still reported the same error.

Using the debugger, I stepped through the program and found the location where the problem was starting. Surprisingly it was transpiring in the pure virtual function “data” at the line where I was checking if the request was referencing the TextAlignmentRole - line 116 in the code listing.


114 QVariant RDDSModel::data(const QModelIndex &index, int role) const
115 {
116 if (role == Qt::TextAlignmentRole)

117 return Qt::AlignCenter;
118
119 ModelItem* pItem;
120 if(role == Qt::DisplayRole){
121 if(index.isValid())
122 pItem = static_cast<ModelItem*>(index.internalPointer());
123 else
124 pItem = pRoot;
125 return pItem->getData(index.column());
126 }
127 return QVariant();
128 }

The actual error message received is...

ASSERT failure in QVector<T>::at: "index out of range"

The debugger indicates that the error is being reported from qvector.h at line 429. Code shown...


427 template <typename T>
428 inline const T &QVector<T>::at(int i) const
429 { Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::at", "index out of range");
430 return d->begin()[i]; }

At this time, I fail to seen any connection to the error message and the code where the error originated. Any help on this issue would be highly appreciated.

d_stranz
23rd May 2018, 00:17
Errors of this sort are invariably a red herring. What has likely happened is that your program has overwritten memory by writing off the end of an array or other local data structure, and that has corrupted the stack. When the stack gets corrupted, the stack pointer can start executing code in a totally unrelated part of your program on the return from the function, so you get errors like this that have nothing to do with the real problem.

The solution is to run your program in the debugger and try to reproduce the error. When it happens, look at the stack traceback until you see a call to a function that makes sense given what you were doing to reproduce the problem. Look there (and in calls preceeding it) for the place where the stack corruption could have occurred.

Corny
23rd May 2018, 16:09
Thank you very much your prompt reply. I don’t know if it’s important, but I think I should point out that when you say I should “try” and reproduce the error, that the error is actually quite consistent, and reproducing it is not an issue. But I did as you suggested and I’m unable to identify any particular problem area. I see the program start, all the Qt calls to paint the window and buttons, and then the mouse handling calls for the button push which leads to the function that is giving the problem. At no point in that chain is there anything that looks odd (not sure I would recognize it if there was) except for just before receiving the error, at lines 78 and 79, there are questions marks and empty brackets. I have no idea whether that is abnormal or not. I’m providing the last part of the backtrace. lines 71 - 79 (following the mouse event). Nothing prior to the mouse event appears anomalous.


#71 0x00de60f4 in QGuiApplicationPrivate::processMouseEvent (e=0x17dbff58) at kernel\qguiapplication.cpp:1927
type = QEvent::MouseButtonRelease
stateChange = {i = 1}
window = 0x17d31ac0
localPoint = {xp = 50, yp = 443}
globalPoint = {xp = 2155, yp = 718}
button = Qt::LeftButton
doubleClick = false
frameStrut = false
ev = {<QInputEvent> = {<QEvent> = {_vptr.QEvent = 0x12a0418 <vtable for QMouseEvent+8>, static staticMetaObject = {d = {superdata = 0x0, stringdata = 0x6be6ba00 <qt_meta_stringdata_QEvent>, data = 0x6be6cee0 <qt_meta_data_QEvent>, static_metacall = 0x0, relatedMetaObjects = 0x0, extradata = 0x0}}, d = 0x0, t = 3, posted = 0, spont = 1, m_accept = 1, reserved = 0}, modState = {i = 0}, ts = 2849}, l = {xp = 50, yp = 443}, w = {xp = 50, yp = 443}, s = {xp = 2155, yp = 718}, b = Qt::LeftButton, mouseState = {i = 0}, caps = 0, velocity = {xp = 0, yp = 0}}

#72 0x00de5678 in QGuiApplicationPrivate::processWindowSystemEvent (e=0x17dbff58) at kernel\qguiapplication.cpp:1711
__PRETTY_FUNCTION__ = "static void QGuiApplicationPrivate::processWindowSystemEvent(Q WindowSystemInterfacePrivate::WindowSystemEvent*)"

#73 0x00dd75d6 in QWindowSystemInterface::sendWindowSystemEvents (flags=...) at kernel\qwindowsysteminterface.cpp:710
event = 0x17dbff58
nevents = 1

#74 0x62a843c9 in QWindowsGuiEventDispatcher::sendPostedEvents (this=0x3e9618) at qwindowsguieventdispatcher.cpp:82
No locals.

#75 0x6bb2a726 in qt_internal_proc(HWND__*, unsigned int, unsigned int, long)@16 (hwnd=0x3805fa <midiStreamPosition+2>, message=1025, wp=0, lp=0) at kernel\qeventdispatcher_win.cpp:221
localSerialNumber = 201
msg = {hwnd = 0x3805fa <midiStreamPosition+2>, message = 1025, wParam = 0, lParam = 0, time = 2677944, pt = {x = 1806871059, y = 0}}
dispatcher = 0x3e9618
result = 0
q = 0x3e9618
d = 0x17d01a68

#76 0x761762fa in gapfnScSendMessage () from C:\Windows\syswow64\user32.dll
No symbol table info available.

#77 0x003805fa in midiStreamPosition () from C:\Windows\system32\winmm.dll
No symbol table info available.

#78 0x00000401 in ?? ()
No symbol table info available.

#79 0x00000000 in ?? ()
No symbol table info available.

d_stranz
23rd May 2018, 16:16
Well then, if it is the mouse button press that seems to trigger the bad behavior, I would start by putting a breakpoint at the start of that slot and stepping through the code line by line (including stepping into any functions called from within the slot) to see if there is something funny going on.

Another test would be to -not- try to reproduce the problem, but to just use whatever you can of the program -without- clicking the button. If at some point it breaks, then it would indicate that the button click is also a red herring and that the corruption is occurring earlier or somewhere else.

Corny
23rd May 2018, 16:24
Thanks again for your assistance. I'll give what you suggest a try.

tuli
25th May 2018, 22:22
Sine you are lucky and Qt tells you exactly where you went wrong, you also breakpoint the QVector::at function shorty before the error occurs and backtrack from there, with the stack intact.

ChristianEhrlicher
27th May 2018, 08:43
121 if(index.isValid())
122 pItem = static_cast<ModelItem*>(index.internalPointer());
123 else
124 pItem = pRoot;
125 return pItem->getData(index.column());

What would you expect here instead of an assertion when index is not valid? Hint: when index is not valid, index.column() will not contain a valid column but -1...

Corny
29th May 2018, 15:30
121 if(index.isValid())
122 pItem = static_cast<ModelItem*>(index.internalPointer());
123 else
124 pItem = pRoot;
125 return pItem->getData(index.column());

What would you expect here instead of an assertion when index is not valid? Hint: when index is not valid, index.column() will not contain a valid column but -1...

Thanks! That pointed out the error of my ways. It seems so obvious now.
Thanks again.

d_stranz
29th May 2018, 16:08
Yes, I did a dope slap on my head as well. Sorry for sending you on a wild goose chase when the problem was staring us in the face. Sometimes no matter how carefully you read code, the obvious escapes you.