Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QScrollbar causing crash on moved



  • Hello, first post here, because I'm in a bind :(

    I'm trying to do a parser/viewer that takes some XML files and display useful data in QTableWidgets.

    So far so good, I've got a QMainWindow with a central widget containing some buttons, that open other forms containing QTableWidget themselves, and some groupboxes with buttons. Foresaid forms are attributes of the central widgets, and not meant to be destroyed before the closing of the app, they are juste shown and hidden (I think).

    The tables contain some data, between thousands and tens of thousands cells for some. They are initialized at the creation of the central widget, within seconds.

    On the first opening (first click on "Open Thistable" button, leading to a slot "Thistable.show", the scrollbars on the side of the tableWidget work fine, no lag or freeze, but if you close the form, and reopen it, suddenly the moving the slider cause a crash.
    The sliderPressed and sliderReleased signals work fine though, but just after the sliderMoved is called (got myself a custom slot saying "hey I'm moving") the app crashes, and gives me a "read access violation at 0x0000000000000008".

    Well, I'm in a pinch, cause I don't ever handle the ScrollBars in my app, the forms are created in Qt Designer, and just filled in my code.
    Any idea on what could cause this, or some tests I could run ?

    Plou <thanks in advance>


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    One thing you can do to find out more information is to run a debug build of your application through the debugger and so get the stack trace associated with your crash.

    By the way:

    • What version of Qt are you using ?
    • What compiler are you using ?
    • What OS are you running ?


  • Hello, thanks for answering so quickly :)

    I'm using 5.12.4, compiling with MSVC2017, on Windows 10.

    So I ran the app through the debugger, and got this stack trace :

    1  QToolBar::setMovable                      Qt5Widgetsd         0x7ffc5eddeb9a 
    2  QToolBar::setMovable                      Qt5Widgetsd         0x7ffc5edd3e23 
    3  QToolBar::setMovable                      Qt5Widgetsd         0x7ffc5ede3e7a 
    4  QToolBar::setMovable                      Qt5Widgetsd         0x7ffc5ee17a61 
    5  QToolBar::setMovable                      Qt5Widgetsd         0x7ffc5ee1248f 
    6  QToolBar::setMovable                      Qt5Widgetsd         0x7ffc5ee69dca 
    7  QToolBar::setMovable                      Qt5Widgetsd         0x7ffc5ee59da6 
    8  QToolBar::setMovable                      Qt5Widgetsd         0x7ffc5f275deb 
    9  QToolBar::setMovable                      Qt5Widgetsd         0x7ffc5f275f2f 
    10 QToolBar::setMovable                      Qt5Widgetsd         0x7ffc5f27ea99 
    11 QToolBar::setMovable                      Qt5Widgetsd         0x7ffc5f2edbf4 
    12 QToolBar::setMovable                      Qt5Widgetsd         0x7ffc5efb7f8a 
    13 QToolBar::setMovable                      Qt5Widgetsd         0x7ffc5efb371c 
    14 QFSFileEngine::copy                       Qt5Cored            0x7ffc5fdb6598 
    15 QFSFileEngine::copy                       Qt5Cored            0x7ffc5fdb5ce8 
    16 QToolBar::setMovable                      Qt5Widgetsd         0x7ffc5efc5dfa 
    17 QToolBar::setMovable                      Qt5Widgetsd         0x7ffc5efc5c03 
    18 QToolBar::setMovable                      Qt5Widgetsd         0x7ffc5efc5a89 
    19 QToolBar::setMovable                      Qt5Widgetsd         0x7ffc5efc577d 
    20 QToolBar::setMovable                      Qt5Widgetsd         0x7ffc5f0f1dfe 
    21 QToolBar::setMovable                      Qt5Widgetsd         0x7ffc5ee5b6c1 
    22 QToolBar::setMovable                      Qt5Widgetsd         0x7ffc5efc5fad 
    23 QToolBar::setMovable                      Qt5Widgetsd         0x7ffc5f0f11fe 
    24 QToolBar::setMovable                      Qt5Widgetsd         0x7ffc5edfc188 
    25 QToolBar::setMovable                      Qt5Widgetsd         0x7ffc5edf7418 
    26 QFSFileEngine::copy                       Qt5Cored            0x7ffc5fd5ef96 
    27 QFSFileEngine::copy                       Qt5Cored            0x7ffc5fd5ee3b 
    28 QToolBar::setMovable                      Qt5Widgetsd         0x7ffc5edfe8e4 
    29 QToolBar::setMovable                      Qt5Widgetsd         0x7ffc5eea6f53 
    30 QToolBar::setMovable                      Qt5Widgetsd         0x7ffc5eea5596 
    31 QToolBar::setMovable                      Qt5Widgetsd         0x7ffc5edfc188 
    32 QToolBar::setMovable                      Qt5Widgetsd         0x7ffc5edf6c0f 
    33 QFSFileEngine::copy                       Qt5Cored            0x7ffc5fd5ef96 
    34 QFSFileEngine::copy                       Qt5Cored            0x7ffc5fd5ee3b 
    35 QOpenGLExtraFunctions::glUseProgramStages Qt5Guid             0x7ffc5d18249e 
    36 QOpenGLExtraFunctions::glUseProgramStages Qt5Guid             0x7ffc5d185213 
    37 QOpenGLExtraFunctions::glUseProgramStages Qt5Guid             0x7ffc5d1531a5 
    38 FT_Property_Set                           qwindowsd           0x7ffc5e865c82 
    39 QFSFileEngine::copy                       Qt5Cored            0x7ffc5fe20148 
    40 CallWindowProcW                           USER32              0x7ffc9ffdb85d 
    41 DispatchMessageW                          USER32              0x7ffc9ffdb1ef 
    42 QFSFileEngine::copy                       Qt5Cored            0x7ffc5fe20a4a 
    43 FT_Property_Set                           qwindowsd           0x7ffc5e865c34 
    44 QFSFileEngine::copy                       Qt5Cored            0x7ffc5fd59173 
    45 QFSFileEngine::copy                       Qt5Cored            0x7ffc5fd593ae 
    46 QFSFileEngine::copy                       Qt5Cored            0x7ffc5fd5cadf 
    47 QOpenGLExtraFunctions::glUseProgramStages Qt5Guid             0x7ffc5d17f838 
    48 QToolBar::setMovable                      Qt5Widgetsd         0x7ffc5edf65ba 
    49 main                                      main.cpp        10  0x7ff6857d2cb9 
    50 WinMain                                   qtmain_win.cpp  97  0x7ff6857da265 
    51 invoke_main                               exe_common.inl  107 0x7ff6857d7d5d 
    52 __scrt_common_main_seh                    exe_common.inl  283 0x7ff6857d7c14 
    53 __scrt_common_main                        exe_common.inl  326 0x7ff6857d7ade 
    54 WinMainCRTStartup                         exe_winmain.cpp 17  0x7ff6857d7de9 
    55 BaseThreadInitThunk                       KERNEL32            0x7ffc9f421fe4 
    56 RtlUserThreadStart                        ntdll               0x7ffca025cb81
    

    So a bunch of tries with setMovable then boom.

    I tried to reproduce my crash on a mini app, and it crashes too. The app only got a MainWindow with a button that opens a form, with the same behavior :

    • button clicked
    • opens form, QTableWidget behaves normally (scrolling H and V works)
    • close the form
    • open it again, with the same button -> crash when trying to scroll

    To create the MainWindow and the form, I just went with Qt Designer as follow :

    • New Qt App, with MainWindow class
    • Add a QPushButton to the MainWindow, set a Vertical layout
    • New Qt Designer Form class, add a QTableWidget, set a vertical layout
    • Add the TableForm to MainWindow as an attribute
    • Connect the button to the show slot in the MainWindow constructor

    mainwindow.cpp

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow),
        _table(new TableForm)
    {
        ui->setupUi(this);
        QObject::connect(ui->butOpen,&QPushButton::clicked,
                         _table, &TableForm::show);
    }
    
    MainWindow::~MainWindow()
    {
        delete _table;
        delete ui;
    }
    

    tableform.cpp

    #include "tableform.h"
    #include "ui_tableform.h"
    
    TableForm::TableForm(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::TableForm)
    {
        ui->setupUi(this);
    
        QStringList head;
        head.append("A"); head.append("A"); head.append("A");
        head.append("A"); head.append("A"); head.append("A");
        head.append("A"); head.append("A"); head.append("A");
        ui->tableTest->setHorizontalHeaderLabels(head);
        ui->tableTest->setColumnCount(head.size());
        ui->tableTest->setRowCount(20);
    }
    
    TableForm::~TableForm()
    {
        delete ui;
    }
    

    main.cpp

    #include "mainwindow.h"
    #include <QApplication>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;
        w.show();
    
        return a.exec();
    }
    

    I'm probably doing something wrong, maybe lacking some signal handling, but I can't pinpoint it.


  • Lifetime Qt Champion

    Can you post the .ui and .pro files ? This will allow to have the same code and build instructions.



  • mainwindow.ui

    <?xml version="1.0" encoding="UTF-8"?>
    <ui version="4.0">
     <class>MainWindow</class>
     <widget class="QMainWindow" name="MainWindow">
      <property name="geometry">
       <rect>
        <x>0</x>
        <y>0</y>
        <width>400</width>
        <height>300</height>
       </rect>
      </property>
      <property name="windowTitle">
       <string>MainWindow</string>
      </property>
      <widget class="QWidget" name="centralWidget">
       <layout class="QVBoxLayout" name="verticalLayout">
        <item>
         <widget class="QPushButton" name="butOpen">
          <property name="text">
           <string>PushButton</string>
          </property>
         </widget>
        </item>
       </layout>
      </widget>
      <widget class="QMenuBar" name="menuBar">
       <property name="geometry">
        <rect>
         <x>0</x>
         <y>0</y>
         <width>400</width>
         <height>20</height>
        </rect>
       </property>
      </widget>
      <widget class="QToolBar" name="mainToolBar">
       <attribute name="toolBarArea">
        <enum>TopToolBarArea</enum>
       </attribute>
       <attribute name="toolBarBreak">
        <bool>false</bool>
       </attribute>
      </widget>
      <widget class="QStatusBar" name="statusBar"/>
     </widget>
     <layoutdefault spacing="6" margin="11"/>
     <resources/>
     <connections/>
    </ui>
    

    tableform.ui

    <?xml version="1.0" encoding="UTF-8"?>
    <ui version="4.0">
     <class>TableForm</class>
     <widget class="QWidget" name="TableForm">
      <property name="geometry">
       <rect>
        <x>0</x>
        <y>0</y>
        <width>400</width>
        <height>300</height>
       </rect>
      </property>
      <property name="windowTitle">
       <string>Form</string>
      </property>
      <layout class="QVBoxLayout" name="verticalLayout">
       <item>
        <widget class="QTableWidget" name="tableTest"/>
       </item>
      </layout>
     </widget>
     <resources/>
     <connections/>
    </ui>
    

    .pro

    QT       += core gui
    
    greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
    
    TARGET = TestSimpleTableWidget
    TEMPLATE = app
    DEFINES += QT_DEPRECATED_WARNINGS
    
    CONFIG += c++11
    
    SOURCES += \
            main.cpp \
            mainwindow.cpp \
            tableform.cpp
    
    HEADERS += \
            mainwindow.h \
            tableform.h
    
    FORMS += \
            mainwindow.ui \
            tableform.ui
    
    # Default rules for deployment.
    qnx: target.path = /tmp/$${TARGET}/bin
    else: unix:!android: target.path = /opt/$${TARGET}/bin
    !isEmpty(target.path): INSTALLS += target
    


  • I've done a little more testing, showing interesting results (I think ?).

    Firstly, I confirmed that the crash happens on a simple implementation without using the designer. (code at the bottom)

    Then, I used testAttribute(Qt::WA_DeleteOnClose) to test and see if the widgets containing the QTableWidget would call their destructors on close, and the flag was not set, neither on the designer test nor on the handcrafted app.

    I tried to tweak the closeEvent, and... it worked ? I did this :

    void TestTableForm::closeEvent(QCloseEvent *event)
    {
        qDebug() << "Closing... Not ! But Hiding.";
        event->ignore();
        this->hide();
    }
    

    And it works, but I don't really see the difference between this, and the closeEvent without the delete-on-close flag.

    Could you explain me, or tell me if this is kind of bad practice and there is a better solution ?

    /// No designer implementation ///
    Edit : code to pastebin



  • @Plou
    I'm lost as to where you're at with all your long code and delete-on-close. But I will say: if you do put Qt::WA_DeleteOnClose on any widget then as soon as it gets closed (not hidden) any attempt to access it from wherever may well lead to an access violation, because it has been deallocated.

    If it helps, I think you can see when that happens by slotting onto the destroyed signal.



  • @JonB
    After re-reading it was not so clear, my bad. I was trying to see if the flag could cause the issue, but it is not set, so I assume it is not.

    I tried some slotting with the destroyed signal, and it figures that the closeEvent does not destroy neither the Widget containing the table, nor the table itself, nor the QScrollBars.

    I tried to reimplement the moveEvent on a custom QScrollBar, and to affect this scrollbar to the view.
    The moveEvent was supposed to display the address of the custom scrollbar, and did it.
    On the first opening of the widget, it works. On the second, it crashes, but before displaying the address, so I think it might not be the moveEvent.

    I cannot pinpoint where the issue comes from. Any idea ?

    Edit : I think it's somewhere after the closeEvent. If I don't ignore the QCloseEvent in the reimplementation of closeEvent in the widget containing my table, it crashes as usual.

    I still don't have any other solution than the previous workaround, ignoring the QCloseEvent.

    What does the QCloseEvent actually do ?


Log in to reply