QGraphicsView::paintEvent crashes



  • I have a QWidget that contains a QGraphicsScene with a single QGraphicsObject. In several situations I need to replace the QGraphicsObject by a new one, and when doing so I also change the sceneRect of the QGraphicsScene (based on the boundingRect of the QGraphicsObject). On certain occasions, my complete application crashes on Linux and the trace given in the debugger does not show any of my code but only Qt code and the last human readable message is on QGraphicsView::paintEvent, see below.

    ??
    ??
    ??
    ??
    ??
    ??
    ??
    ??
    QGraphicsView::paintEvent(QPaintEvent *)
    QWidget::event(QEvent *)
    QFrame::event(QEvent *)
    QGraphicsView::viewportEvent(QEvent *)
    QCoreApplicationPrivate::sendThroughObjectEventFilters(QObject *, QEvent *)
    QApplicationPrivate::notify_helper(QObject *, QEvent *)
    QApplication::notify(QObject *, QEvent *)
    QCoreApplication::notifyInternal2(QObject *, QEvent *)
    QWidgetPrivate::sendPaintEvent(QRegion const&)
    QWidgetPrivate::drawWidget(QPaintDevice *, QRegion const&, QPoint const&, int, QPainter *, QWidgetBackingStore *)
    ??
    ??
    QWidgetPrivate::syncBackingStore()
    QWidget::event(QEvent *)
    QMainWindow::event(QEvent *)
    QApplicationPrivate::notify_helper(QObject *, QEvent *)
    QApplication::notify(QObject *, QEvent *)
    QCoreApplication::notifyInternal2(QObject *, QEvent *)
    QCoreApplicationPrivate::sendPostedEvents(QObject *, int, QThreadData *)
    ??
    ??
    QObject::event(QEvent *)
    QGraphicsScene::event(QEvent *)
    QApplicationPrivate::notify_helper(QObject *, QEvent *)
    QApplication::notify(QObject *, QEvent *)
    QCoreApplication::notifyInternal2(QObject *, QEvent *)
    QCoreApplicationPrivate::sendPostedEvents(QObject *, int, QThreadData *)
    ??
    g_main_context_dispatch
    ??
    g_main_context_iteration
    QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>)
    QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>)
    QCoreApplication::exec()
    main
    

    On MacOS and Windows (MinGW) there is no crash when replacing the QGraphicsObject, but a crash occurs at closing/destroying the complete Widget.

    I have not reimplemented this paintEvent method in any way, so I guess I am doing something else wrong. The strange thing is however that in many situations it does work fine. Here is the code that I use to replace the QGraphicsObject, which is called Diagram:

    Scene->removeItem(Diagram);
    delete Diagram;
    setupDiagram();      // This creates the new QGraphicsObject and assigns it to variable Diagram
    QRectF Rect = Diagram->boundingRect();
    Rect.adjust(-40, -40, 40, 40);
    Scene->setSceneRect(Rect);
    Scene->addItem(Diagram);
    

    Hopefully, somebody has an idea where I should start looking to find out what is wrong as I have no clue at all...



  • From the docs:

    void QGraphicsScene::removeItem(QGraphicsItem *item)
    Removes the item item and all its children from the scene. The ownership of item is passed on to the caller (i.e., QGraphicsScene will no longer delete item when destroyed).

    Could it be that while the item is removed from the scene while it is not deleted?



  • The way I understand the documentation is that I have to delete the removed item myself, which is what I do in the second line.



  • Yes, but does setupDiagram() check if the Diagram item is indeed deleted?


  • Lifetime Qt Champion

    Hi,

    QGraphicsObject being a QObject, you should rather call deleteLater on it. That way the event loop handle its deletion.



  • @Jan-Willem
    No, how can I do that?

    @SGaist
    Using deleteLater does not make the crash disappear...


  • Lifetime Qt Champion

    Where are you calling that code from ?



  • The code I gave is called from the QWidget that contains the QGraphicsScene Scene, which has this QGraphicsObject Diagram as item. I have a destructor of the Widget that deletes Diagram, but perhaps that is not needed as it is a QObject?

    Edit: removing my destructor does not change a thing wrt the crashes...

    What are typical situations to use deleteLater instead of delete?


  • Qt Champions 2016

    @ModelTech said in QGraphicsView::paintEvent crashes:

    What are typical situations to use deleteLater instead of delete?

    In almost all situations it's preferred when dealing with QObject instances.

    On certain occasions, my complete application crashes on Linux and the trace given in the debugger does not show any of my code but only Qt code and the last human readable message is on QGraphicsView::paintEvent, see below.

    Eh, your stack trace is full of holes, sadly. Are you sure you're getting it from a debug build of your application?



  • @kshegunov
    Thanks for the clarification on the deleteLater, I will change my code accordingly.

    The holes are indeed what I get from the debugger, showing assembly code when inspecting...


  • Qt Champions 2016

    @ModelTech said in QGraphicsView::paintEvent crashes:

    The holes are indeed what I get from the debugger, showing assembly code when inspecting...

    Which just strengthens my suspicion you're debugging a release build, could you please check that?



  • I am using a debug build, but I have investigated changing it to a release build, just to see the difference in error message. Conclusion: there is no difference...

    The fact that changing the build type was effective is seen from a difference in one warning that I get during compilation for the release build that I do not get for a debug build (it is about a variable that may be uninitialized, which in this case cannot occur in practice).


  • Lifetime Qt Champion

    Why can it not occur in practice ?



  • @SGaist Well, the considered code looks currently like this (where the warning is on variable Label). Perhaps I should change the third if into an else to avoid the warning. Anyway, changing this does not solve the crashing problem (I tried) as it is in a totally different/unrelated part of my code.

    if (Specification->isCSDFActor() || Specification->isDetector()) {
        QLabel *Label;
        if (Specification->isCSDFActor())
            Label = new QLabel(tr("<strong>Phases</strong>"), this);
        if (Specification->isDetector())
            Label = new QLabel(tr("<strong>SubScenarios</strong>"), this);
        QVBoxLayout *SubScenarioLayout = new QVBoxLayout;
        SubScenarioLayout->addWidget(Label);
    }
    

  • Lifetime Qt Champion

    With the code at hand then indeed, it should not happen.

    To be on the clean and safe side, I'd rather write QLabel *Label = Q_NULLPTR; or QLabel *Label = nullptr;


  • Qt Champions 2016

    I realized that it may be system calls that are made in those stack holes. The most often crash I've encountered in the event loops is when an object is passed to Qt and it's subsequently deleted while events intended for it are still pending. I think you should check that this doesn't happen here..



  • Ok, that sounds like a scenario that could be the case here. Is there an easy way to check whether events are pending for an object? Is there a way to clear the buffer holding events for an object that I could perhaps call before using delete/deleteLater?


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.