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>
-
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.
-
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 putQt::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 thecloseEvent
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.
ThemoveEvent
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 themoveEvent
.I cannot pinpoint where the issue comes from. Any idea ?
Edit : I think it's somewhere after the
closeEvent
. If I don't ignore theQCloseEvent
in the reimplementation ofcloseEvent
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 ?
-
@JonB @Plou I have exactly the same problem in the exact same scenario. I am using PyQt5 UI code generator 5.14.1 and Qt Designer 5.12.8. I tried to figure it out but had no success till now. My code crashes without throwing any error, but when I put these lines in my code.
"""
scroller = QScroller.scroller(self.listWidget)
gesture = QScroller.TouchGesture
scroller.grabGesture(self.listWidget, gesture)
"""
When this mainWindow was open for the second or third time not on the first attempt.
I have custom Rasbian running on RaspberryPI.