Solved Intermittent crash in QGraphicsScene
-
@kshegunov said in Intermittent crash in QGraphicsScene:
Are you sure you don't use delete anywhere?
Yes - literally the only
delete
s in this code are in dialog class destructors, and those are only used at the end of the program execution (all of my dialogs are constructed up front and stored for later use).I'm trying it without the BSP tree now (it takes a while to generate the crash, so I can't tell yet whether it worked).
-
No luck on disabling the BSP tree index, the code still crashes in the same place. If I look at the QGraphicsLineItem object with the broken pen, although pen->d is null, line->d is not, and shows a set of coordinates that cannot actually be a line I have drawn in my code (it's diagonal, all of mine are perfectly vertical or horizontal). I can't tell if that's a clue or if it's an artifact of the same thing that is breaking the pen.
-
@Chris-Hennes said in Intermittent crash in QGraphicsScene:
No luck on disabling the BSP tree index, the code still crashes in the same place.
I don't see how that's possible, as
_q_updateIndex
is specific to BSP indexing.I can't tell if that's a clue or if it's an artifact of the same thing that is breaking the pen.
Probably unreliable. If the pen is null you can't be sure the object holding the pen's valid - the rationale is like with the 13th clock stroke.
-
@kshegunov said in Intermittent crash in QGraphicsScene:
I don't see how that's possible, as _q_updateIndex is specific to BSP indexing.
Sorry I wasn't clear: when I said "in the same place" I was referring to
1 QPen::widthF qpen.cpp 636
The path to get there is different, but it's still ultimately doing the same thing, and still crashing under the same circumstances. The new call stack is:
1 QPen::widthF qpen.cpp 636 0x7fff9217711d 2 QGraphicsLineItem::boundingRect qgraphicsitem.cpp 9386 0x55f6dec7 3 QGraphicsItemPrivate::effectiveBoundingRect qgraphicsitem.cpp 2960 0x55f77cc6 4 adjustedItemEffectiveBoundingRect qgraphicsscene_p.h 353 0x55fbfe43 5 QGraphicsScenePrivate::processDirtyItemsRecursive qgraphicsscene.cpp 5205 0x55fba406 6 QGraphicsScenePrivate::_q_processDirtyItems qgraphicsscene.cpp 487 0x55fb105e 7 QGraphicsScene::qt_static_metacall moc_qgraphicsscene.cpp 184 0x55fa7966 8 QMetaCallEvent::placeMetaCall qobject.cpp 504 0x55255821 9 QObject::event qobject.cpp 1246 0x5524e17f 10 QGraphicsScene::event qgraphicsscene.cpp 3523 0x55fad6f8 11 QApplicationPrivate::notify_helper qapplication.cpp 3717 0x559d6f3e 12 QApplication::notify qapplication.cpp 3089 0x559d1973 13 QCoreApplication::notifyInternal2 qcoreapplication.cpp 1018 0x551f61f6 14 QCoreApplication::sendEvent qcoreapplication.h 233 0x552010b2 15 QCoreApplicationPrivate::sendPostedEvents qcoreapplication.cpp 1678 0x551f7ab2 16 QEventDispatcherWin32::sendPostedEvents qeventdispatcher_win.cpp 1063 0x552b1dea 17 QWindowsGuiEventDispatcher::sendPostedEvents qwindowsguieventdispatcher.cpp 82 0x7fff9a2dfd74 18 qt_internal_proc qeventdispatcher_win.cpp 236 0x552afacd 19 UserCallWinProcCheckWow USER32 0x7fffdb8dbc50 20 DispatchMessageWorker USER32 0x7fffdb8db5cf ... <More>
-
Mind sharing some code - how you clear and create the scene items. I can't tell anything to be plainly wrong by looking at the trace. Perhaps try "delaying" the item reinsertions by some time (e.g. few seconds) to see if it's not some kind event concurrency problem ...?
-
It looks like the following code is the culprit:
if (_selectionRegion && _scene.items().contains(_selectionRegion)) { _selectionRegion->setRect (r); } else { QPen pen (Qt::black); QBrush brush (QColor(0,0,0,70)); _selectionRegion = _scene.addRect (r, pen, brush); }
In particular, something about that first "if" clause. If I just let the thing rebuild the rectangle every time it does not crash (e.g. I comment out the conditional and just execute the second path). This bit of code is called in a number of places, including at the beginning of execution, and at various times pre- and post-
clear()
. -
Then
selectionRegion
is probably deleted (or not yet created) at the moment that you use it. If deleted you can set a breakpoint in the object's destructor and see in the backtrace where this deletion comes from.-Michael.
-
Well, I know exactly where it's being deleted -- in the calls to
clear()
. But it seemed to me that those calls would result in_scene.items().contains(_selectionRegion)
returningfalse
. And while this seems to be true most of the time, every once in a while it's not. The rectangle is invalid, but is still in the items list.So, the current workaround (which is being stress-tested as I type) is that the superclass which calls
clear()
now instead calls a virtual function that callsclear()
. In the subclass that owns_selectionRegion
I overload this virtual function, call the parent (thereby callingclear()
) and then explicitly nullify_selectionRegion
. Hopefully this sequence prevents any queued events from calling the_selectionRegion
update code in between calls toclear()
and the nullification of the member. I've managed to type this whole thing without the code crashing yet, so this looks promising. -
@Chris-Hennes
hi, I think the easiest solution would be settingselectionRegion
to a Nullpointer after the clear cmdselectionRegion->clear(); selectionReadion = Q_NULLPTR;
that way the first part of your if condition will return false and not crash.
-
Right, that's essentially the solution I've got, with the caveat that
clear()
is called by a superclass that knows nothing about the_selectionRegion
so I had to do a bit of refactoring to achieve that effect. The crash seems to be gone with that change, so I'm going to mark this as solved here (and in GitHub). But we all know how this type of bug goes, I might be back tomorrow :/ -
@Chris-Hennes said in Intermittent crash in QGraphicsScene:
But we all know how this type of bug goes, I might be back tomorrow :/
In either case, please report it to the bugtracker. It might not get fixed soon, or ever, but it's a good idea to be there so others won't struggle with this as much as you had.