I have developed an app in Qt/C++, it's a file browser like. Currently when deleting some files or copying some files, I have a thread who manage the overall app and copy and another one just created to display a progress bar with the Cancel button. It's very basic but as I'm browsing an Android device file system any access to delete copy freeze the UI and the access is done by the application thread. It's not an issue as I don't want the user to play with the UI when copying or deleting.
My issue is mainly a real time issue with the threading. When I'm using Qt creator as IDE and debugging, I do not have any issue the delete works and the progress bar is also display without any issue. When I'm just using the app out of Qt Creator the app is crashing often when trying to display the dialog box.
I'm pretty sure it's link to the threading. when using the debugger and Qt creator the overall app slowing down to trace, debug...
Here is the code of my TreeView.cpp when asking to delete for example:
DialogProgressIndicator *DeleteProgress = new DialogProgressIndicator;
DeleteProgress->moveToThread(&ProgressThread);
connect(&ProgressThread, &QThread::finished, DeleteProgress, &QObject::deleteLater);
connect(this, &PulsTreeWidget::DisplayProgress, DeleteProgress, &DialogProgressIndicator::ShowDlg);
connect(this, &PulsTreeWidget::UpdateProgress, DeleteProgress, &DialogProgressIndicator::UpdateIndicator);
connect(this, &PulsTreeWidget::CloseProgress, DeleteProgress, &DialogProgressIndicator::CloseDlg);
connect(DeleteProgress,&DialogProgressIndicator::CancelAction, this, &PulsTreeWidget::CatchActionCancel);
ProgressThread.start();
DisplayProgress();
And when the delete is finished, I'm closing everything following the method below:
CloseProgress();
ProgressThread.quit();
disconnect(&ProgressThread, &QThread::finished, FileTransferProgress, &QObject::deleteLater);
disconnect(this, &PulsTreeWidget::DisplayProgress, FileTransferProgress, &DialogProgressIndicator::ShowDlg);
disconnect(this, &PulsTreeWidget::UpdateProgress, FileTransferProgress, &DialogProgressIndicator::UpdateIndicator);
disconnect(this, &PulsTreeWidget::CloseProgress, FileTransferProgress, &DialogProgressIndicator::CloseDlg);
disconnect(FileTransferProgress,&DialogProgressIndicator::CancelAction, this, &PulsTreeWidget::CatchActionCancel);
the class PulsTreeWidget is defined as below:
class PulsTreeWidget : public QTreeWidget
{
Q_OBJECT
QThread ProgressThread;
public:
PulsTreeWidget(PulsDeviceMngr& device, PulsMainUI& parent);
~PulsTreeWidget();
signals:
void DisplayProgress();
void CloseProgress();
void UpdateProgress(int);
The Progress bar is managed by the class
DialogProgressIndicator.cpp
#include <QApplication>
#include "dialogprogressindicator.h"
#include "ui_dialogprogressindicator.h"
DialogProgressIndicator::DialogProgressIndicator(QWidget *parent) :
QDialog(parent),
ui(new Ui::DialogProgressIndicator)
{
ui->setupUi(this);
ui->progressBar->setRange(0,100);
ui->progressBar->setValue(1);
connect(ui->Cancel, SIGNAL(clicked()), this, SLOT(onClickCancel()));
}
void DialogProgressIndicator::ShowDlg() {
ui->progressBar->show();
}
void DialogProgressIndicator::CloseDlg() {
ui->progressBar->close();
}
DialogProgressIndicator::~DialogProgressIndicator()
{
delete ui;
}
void DialogProgressIndicator::UpdateIndicator(int value) {
ui->progressBar->setValue(value);
QApplication::processEvents();
}
void DialogProgressIndicator::onClickCancel() {
emit CancelAction();
disconnect(ui->Cancel, SIGNAL(clicked()), this, SLOT(onClickCancel()));
}
I have followed the Qt guideline but it still crashing when doing the "DisplayProgress"
Any idea ? It's really crashing when in the other thread I'm doing the
void DialogProgressIndicator::ShowDlg() {
ui->progressBar->show();
}
I'm adding the crash log:
Application Specific Information:
abort() called
Thread 0:: Dispatch queue: com.apple.main-thread
0 com.apple.AppKit 0x00007fff89e6561f -[NSView(NSInternal) _allocAuxiliary:] + 833
1 com.apple.AppKit 0x00007fff89e67a59 -[NSView _commonAwake] + 36
2 com.apple.AppKit 0x00007fff89e6c841 -[NSView initWithFrame:] + 457
3 libqcocoa.dylib 0x0000000103c2078f 0x103c0c000 + 83855
4 libqcocoa.dylib 0x0000000103c20a1d 0x103c0c000 + 84509
5 libqcocoa.dylib 0x0000000103c18f36 0x103c0c000 + 53046
6 libqcocoa.dylib 0x0000000103c14b72 0x103c0c000 + 35698
7 QtGui 0x0000000100f77603 QWindow::create() + 51
8 QtWidgets 0x0000000101509e13 QWidgetPrivate::create_sys(unsigned long long, bool, bool) + 1107
9 QtWidgets 0x00000001014df86c QWidget::create(unsigned long long, bool, bool) + 444
10 QtWidgets 0x00000001014eeebd QWidget::setVisible(bool) + 237
11 QtWidgets 0x000000010169679d QDialog::setVisible(bool) + 205
12 com.yourcompany.puls_connect 0x0000000100022305 DialogProgressIndicator::ShowDlg() + 21
13 com.yourcompany.puls_connect 0x000000010001a51e void QtPrivate::FunctionPointer<void (DialogProgressIndicator::*)()>::call<void, void>(void (DialogProgressIndicator::*)(), DialogProgressIndicator*, void**) + 142
14 com.yourcompany.puls_connect 0x000000010001a3fa QtPrivate::QSlotObject<void (DialogProgressIndicator::*)(), void, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) + 202
15 QtCore 0x0000000100bfdda2 QMetaObject::activate(QObject*, int, int, void**) + 1874
16 com.yourcompany.puls_connect 0x00000001000242db PulsTreeWidget::DisplayProgress() + 43
Remember that you can use GUI classes only in main thread. For parallel task use
QFutureWatcher:
WaitDialog waitDlg(this);
connect(this, SIGNAL(progress(int)), &waitDlg, SLOT(setProgress(int)));
QFutureWatcher<void> watcher;
connect(&watcher, SIGNAL(finished()), &waitDlg, SLOT(close()));
connect(&watcher, SIGNAL(canceled()), &waitDlg, SLOT(close()));
QFuture<void> future = QtConcurrent::run([] () {/*do parallel task here*/});
watcher.setFuture(future);
waitDlg.exec();
Related
I have the following use case (doesn't really make sense, because it's minimized from a real-life working example, however I think it's still technically correct):
class Dialog : public QDialog
{
public:
Dialog(QWidget* parent)
: QDialog(parent)
{
new Q3ListView(this); // this will crash
// new QWidget(this); // this won't crash
}
};
Depending on what is added to the Dialog the program will crash or not when deleting the Dialog instance (as indicated by the comments in the snippet), but only when main window's flags have been modified. Here is the code for the MainWindow class, which uses Dialog:
class MainWindow : public QMainWindow
{
public:
// the fact that the widget (dialog) below
// has no chance to show seems irrelevant.
// In the real scenario I have, the widget is shown on
// the screen and is closed by the user.
// I've just put the whole sequence of pieces of code
// that result from signal/slot calls, that in turn
// result from a point&click scenario in our application
// into the following function for brevity.
void go()
{
auto dialog = new Dialog(this);
dialog->show();
dialog->close();
disableAlwaysOnTop();
delete dialog; // or dialog->deleteLater();
}
void disableAlwaysOnTop()
{
setAttribute(Qt::WA_Resized, true);
Qt::WindowFlags flags = windowFlags();
setWindowFlags(flags ^ (Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint));
setVisible(true);
}
};
and the implementation of main:
int main(int argc, char** argv)
{
QApplication app(argc, argv);
MainWindow mainWindow;
mainWindow.show();
mainWindow.go();
return app.exec();
}
All lines seem essential to reproduce the crash.
Is it a bug in Qt, or am I doing something wrong?
Manually deleting widget's children is allowed, and they should automatically unregister from their parents as indicated in the quote from the manual below. In my real-life case the widget is deleted to disappear from the GUI, and it works in case of other widget combinations. As indicated in the comment above, changing delete dialog; to dialog->deleteLater(); doesn't help.
It seems that there is a problem in removing the Q3ListView instance from Qt's backing store, here is the stack trace:
QtGuid4.dll!QWidgetBackingStore::staticContents(QWidget * parent, const QRect & withinClipRect) Line 499 C++
QtGuid4.dll!QWidgetBackingStore::sync() Line 1200 C++
QtGuid4.dll!QWidgetPrivate::syncBackingStore() Line 1896 C++
QtGuid4.dll!QWidget::event(QEvent * event) Line 8694 C++
QtGuid4.dll!QMainWindow::event(QEvent * event) Line 1479 C++
QtGuid4.dll!QApplicationPrivate::notify_helper(QObject * receiver, QEvent * e) Line 4565 C++
QtGuid4.dll!QApplication::notify(QObject * receiver, QEvent * e) Line 4530 C++
QtCored4.dll!QCoreApplication::notifyInternal(QObject * receiver, QEvent * event) Line 955 C++
QtCored4.dll!QCoreApplication::sendEvent(QObject * receiver, QEvent * event) Line 231 C++
QtCored4.dll!QCoreApplicationPrivate::sendPostedEvents(QObject * receiver, int event_type, QThreadData * data) Line 1579 C++
QtCored4.dll!qt_internal_proc(HWND__ * hwnd, unsigned int message, unsigned __int64 wp, __int64 lp) Line 498 C++
[External Code]
QtCored4.dll!QEventDispatcherWin32::processEvents(QFlags flags) Line 823 C++
QtGuid4.dll!QGuiEventDispatcherWin32::processEvents(QFlags flags) Line 1216 C++
QtCored4.dll!QEventLoop::processEvents(QFlags flags) Line 150 C++
QtCored4.dll!QEventLoop::exec(QFlags flags) Line 204 C++
QtCored4.dll!QCoreApplication::exec() Line 1227 C++
QtGuid4.dll!QApplication::exec() Line 3824 C++
qt_bug.exe!main(int argc, char * * argv) Line 60 C++
And the piece of Qt's code that attempts to use a pointer to a deleted object in the line indicated in the stack trace:
for (int i = 0; i < count; ++i) {
QWidget *w = staticWidgets.at(i);
QWidgetPrivate *wd = w->d_func();
if (!wd->isOpaque || !wd->extra || wd->extra->staticContentsSize.isEmpty() // ****
|| !w->isVisible() || (parent && !parent->isAncestorOf(w))) {
continue;
}
(wd points to a deleted object at the line marked with the comment).
Disclaimer:
I know that more elegant solutions exist but this is legacy code, and according to Qt's manual:
You can also delete child objects yourself, and they will remove themselves from their parents.
this code is valid.
We've reproduced the problem on Windows 7 (MSVC 2010 SP1, CL 16), Windows 8 (MSVC 2013 U4, CL 18) and Fedora 20 (GCC 4.8.3).
I've filed a bug report. Since it concerns an old version of the library no hopes that it will be fixed.
We are successively removing Qt3Support anyway and so is everyone advised ;)
I know that you need to reimplement the QApplication::notify() method to properly catch exceptions thrown from the main thread's event handlers.
But what about other threads? Say, I have an object with a slot, and this object lives in a QThread (with default run() method, which just calls exec()), i.e. the thread affinity of this object is the background QThread. So, where should I catch exceptions thrown from this object's slot?
IOW, how do I reimplement the notify() method of a background thread?
When you create your Custom Application with overriden notify method; the QThread you create uses this overriden method too (as the main thread) once it has started its own event loop
It means in practice that if you connect any slot to the QThread::started signal; then this slot executes outside the event loop of thethread, thus not in the overriden notify method.
Here is a sample of code that helps to understand what happen:
#include "mainwindow.h"
#include <QApplication>
#include <QDebug>
#include <QThread>
#include <QTimer>
#include <exception>
class ThrowingObject : public QObject
{
public:
void doThrowInNotify()
{
qDebug() << "I am execution on thread id" << QThread::currentThreadId() << " and I am throwing";
throw std::exception("KBOOOM");
}
void scheduleThrow()
{
QTimer* singleShot = new QTimer(this);
singleShot->setSingleShot(true);
connect(singleShot, &QTimer::timeout, this, &ThrowingObject::doThrow);
singleShot->start();
qDebug() << "I am execution on thread id" << QThread::currentThreadId() << " and I will throw in run";
}
void doThrow()
{
qDebug() << "I am execution on thread id" << QThread::currentThreadId() << " and I am throwing right now";
//This exception is not catched, and definitly crash the process
throw std::exception("KBOOOM");
}
void doThrowOutsideNotify()
{
//wait 5s for demo purpose, this slot is called by Object2, after Object1 throw in thread1 event loop
QThread::sleep(5);
qDebug() << "I am execution on thread id" << QThread::currentThreadId() << " and I am throwing right now";
//This exception is not catched, and definitly crash the process
throw std::exception("FATAL KBOOOM");
}
};
class ApplicationWithExceptionCatchedInNotify : public QApplication
{
public:
ApplicationWithExceptionCatchedInNotify(int argc, char *argv[]) :
QApplication(argc,argv)
{}
bool notify(QObject* receiver, QEvent *e) override
{
try {
return QApplication::notify(receiver, e);
}
catch(std::runtime_error e)
{
qDebug() << "std::runtime_error in thread : " << QThread::currentThreadId();
qDebug() << e.what();
}
catch(std::exception e)
{
qDebug() << "std::exception in thread : " << QThread::currentThreadId();
qDebug() << e.what();
}
catch(...)
{
qDebug() << "exception thread : " << QThread::currentThreadId();
}
qDebug() << "catch in notify ";
return false;
}
};
int main(int argc, char *argv[])
{
ApplicationWithExceptionCatchedInNotify app(argc, argv);
qDebug() << "Main QThread id" << QThread::currentThreadId();
//Object o1 will throw in its event loop (in notify)
QThread thread1;
ThrowingObject o1;
o1.moveToThread(&thread1);
QObject::connect(&thread1, &QThread::started, &o1, &ThrowingObject::scheduleThrow);
thread1.start();
//Object o2 will throw before the event loop is installed
QThread thread2;
ThrowingObject o2;
o2.moveToThread(&thread2);
//Connect to started signal.
QObject::connect(&thread2, &QThread::started, &o2, &ThrowingObject::doThrowOutsideNotify);
thread2.start();
app.exec();
}
Running this code sample on windows , Qt 5.9 with Qt creator gives for example :
Output :
Main QThread id 0x11e4
I am execution on thread id 0x180c and I will throw in run
I am execution on thread id 0x180c and I am throwing right now
std::exception in thread : 0x180c
KBOOOM
catch in notify
I am execution on thread id 0x27b8 and I am throwing right now
and a Microsoft Visual Studio Runtime Library pop up crying that :
Microsoft Visual C++ Runtime Library
Debug Error!
Program: ...ad-Desktop_Qt_5_9_2_MSVC2017_64bit-Debug\debug\DemoThread.exe
abort() has been called
(Press Retry to debug the application)
If you put breakpoint; once can realize that :
Object o1 throws in QThread::exec methods, going down the callstack we can see we are in ApplicationWithExceptionCatchedInNotify::Notify
1 ThrowingObject::doThrow main.cpp 35 0x7ff66615352b
2 QtPrivate::FunctorCall,QtPrivate::List<>,void,void (__cdecl ThrowingObject:: *)(void) __ptr64>::call qobjectdefs_impl.h 136 0x7ff66615358c
3 QtPrivate::FunctionPointer::call,void> qobjectdefs_impl.h 170 0x7ff666152ce7
4 QtPrivate::QSlotObject,void>::impl qobject_impl.h 121 0x7ff66615363e
5 QtPrivate::QSlotObjectBase::call qobject_impl.h 101 0x54a82428
6 QMetaObject::activate qobject.cpp 3754 0x54a70ee0
7 QMetaObject::activate qobject.cpp 3629 0x54a707a8
8 QTimer::timeout moc_qtimer.cpp 202 0x54a8f739
9 QTimer::timerEvent qtimer.cpp 257 0x54a8f79a
10 QObject::event qobject.cpp 1228 0x54a72b73
11 QApplicationPrivate::notify_helper qapplication.cpp 3722 0x53aeb8ee
12 QApplication::notify qapplication.cpp 3094 0x53ae6323
13 ApplicationWithExceptionCatchedInNotify::notify main.cpp 60 0x7ff666158730
14 QCoreApplication::notifyInternal2 qcoreapplication.cpp 1018 0x54a1b0c6
15 QCoreApplication::sendEvent qcoreapplication.h 233 0x54a26062
16 QEventDispatcherWin32::event qeventdispatcher_win.cpp 1041 0x54ad8cab
17 QApplicationPrivate::notify_helper qapplication.cpp 3722 0x53aeb8ee
18 QApplication::notify qapplication.cpp 3094 0x53ae6323
19 ApplicationWithExceptionCatchedInNotify::notify main.cpp 60 0x7ff666158730
20 QCoreApplication::notifyInternal2 qcoreapplication.cpp 1018 0x54a1b0c6
21 QCoreApplication::sendEvent qcoreapplication.h 233 0x54a26062
22 QCoreApplicationPrivate::sendPostedEvents qcoreapplication.cpp 1678 0x54a1c982
23 QEventDispatcherWin32::sendPostedEvents qeventdispatcher_win.cpp 1064 0x54ad8e6a
24 qt_internal_proc qeventdispatcher_win.cpp 237 0x54ad6b47
25 CallWindowProcW USER32 0x7ffba1571c24
26 DispatchMessageW USER32 0x7ffba157156c
27 QEventDispatcherWin32::processEvents qeventdispatcher_win.cpp 628 0x54ad755b
28 QEventLoop::processEvents qeventloop.cpp 135 0x54a15498
29 QEventLoop::exec qeventloop.cpp 212 0x54a156de
30 QThread::exec qthread.cpp 515 0x5465028f
31 QThread::run qthread.cpp 583 0x546501c3
32 QThreadPrivate::start qthread_win.cpp 380 0x5465caed
33 BaseThreadInitThunk KERNEL32 0x7ffb9f5b8364
34 RtlUserThreadStart ntdll 0x7ffba1bb7091
Object o2 throws in QThread::start methods; outside of the thread2 event loop
1 ThrowingObject::doThrowOutsideNotify main.cpp 45 0x7ff666152ba6
2 QtPrivate::FunctorCall,QtPrivate::List<>,void,void (__cdecl ThrowingObject:: *)(void) __ptr64>::call qobjectdefs_impl.h 136 0x7ff66615358c
3 QtPrivate::FunctionPointer::call,void> qobjectdefs_impl.h 170 0x7ff666152ce7
4 QtPrivate::QSlotObject,void>::impl qobject_impl.h 121 0x7ff66615363e
5 QtPrivate::QSlotObjectBase::call qobject_impl.h 101 0x54a82428
6 QMetaObject::activate qobject.cpp 3754 0x54a70ee0
7 QMetaObject::activate qobject.cpp 3629 0x54a707a8
8 QThread::started moc_qthread.cpp 160 0x54650149
9 QThreadPrivate::start qthread_win.cpp 377 0x5465cad6
10 BaseThreadInitThunk KERNEL32 0x7ffb9f5b8364
11 RtlUserThreadStart ntdll 0x7ffba1bb7091
Since certain version of Qt5, the QCoreApplication::notify manual says:
this function is called for all events sent to any object in any
thread.
So this means that the correct answer to my original question was "just do what you were doing all along".
Funnily, just as I discovered this, this newly discovered knowledge instantly became outdated by this phrase from the very same manual:
This function will not be called for objects that live outside the
main thread in Qt 6. Applications that need that functionality should
find other solutions for their event inspection needs in the meantime.
The change may be extended to the main thread, causing this function
to be deprecated.
LOL. I have not migrated to Qt6 yet so I have no idea what's the situation there, but when I do, I might just re-open this exact question.
The following application crashes on mainWindow->show();
#include <QApplication>
#include <QFrame>
#include <QPixmap>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Q_INIT_RESOURCE(resources);
QPixmap pix;
pix.load(":/resources/images/app/icon_glow.png");
QFrame *mainWindow = new QFrame;
mainWindow->setWindowIcon(QIcon(pix));
mainWindow->show();
return a.exec();
}
With the mainWindow->setWindowIcon(QIcon(pix)); commented out, everything works. Otherwise, the backtrace (SEGFAULT, trying to dereference 0x8; seems like a missing nullptr check somewhere) is:
0 ?? /usr/local/Qt32/5.3/gcc/plugins/platforms/libqxcb.so 0xf4991138
1 ?? /usr/local/Qt32/5.3/gcc/plugins/platforms/libqxcb.so 0xf4982d4c
2 ?? /usr/local/Qt32/5.3/gcc/plugins/platforms/libqxcb.so 0xf498e7e3
3 ?? /usr/local/Qt32/5.3/gcc/plugins/platforms/libqxcb.so 0xf498f0f4
4 QWindowPrivate::applyCursor() /usr/local/Qt32/5.3/gcc/lib/libQt5Gui.so.5 0xf7517942
5 QWindowPrivate::setCursor(QCursor const*) /usr/local/Qt32/5.3/gcc/lib/libQt5Gui.so.5 0xf75179f7
6 QWindow::setCursor(QCursor const&) /usr/local/Qt32/5.3/gcc/lib/libQt5Gui.so.5 0xf7517b16
7 ?? /usr/local/Qt32/5.3/gcc/lib/libQt5Widgets.so.5 0xf7ad5d65
8 QWidgetPrivate::show_sys() /usr/local/Qt32/5.3/gcc/lib/libQt5Widgets.so.5 0xf7ad60b6
9 QWidgetPrivate::show_helper() /usr/local/Qt32/5.3/gcc/lib/libQt5Widgets.so.5 0xf7abab35
10 QWidget::setVisible(bool) /usr/local/Qt32/5.3/gcc/lib/libQt5Widgets.so.5 0xf7abb005
11 QWidget::show() /usr/local/Qt32/5.3/gcc/lib/libQt5Widgets.so.5 0xf7aad77e
12 main main.cpp 17 0x804a21f
I tried loading the resource as follows:
QLabel *mainLabel = new QLabel;
mainLabel->setPixmap(pix);
mainLabel->show();
That works without a problem. Any help is greatly appreciated. Ubuntu 14.04 x64, compiled 32 bit, Qt 5.3
UPDATE: I reinstalled ubuntu-desktop (i reverted the desktop from 32 bit to 64 bit) and now I get an error:
The X11 connection broke: Maximum allowed requested length exceeded (code 4)
XIO: fatal IO error 2 (No such file or directory) on X server ":0"
after 409 requests (409 known processed) with 0 events remaining.
I have also encountered this. The reason is the icon is too large. Resize to something smaller, 256x256 for example.
Just recently I've installed the Qt libraries on my computer, and as a complete novice I looked up the Qt 4.7 Getting Started guides online.
Just on the first page they provide the following code:
1 #include <QtGui>
2
3 int main(int argv, char **args)
4 {
5 QApplication app(argv, args);
6
7 QTextEdit textEdit;
8 QPushButton quitButton("Quit");
9
10 QObject::connect(&quitButton, SIGNAL(clicked()), qApp, SLOT(quit()));
11
12 QVBoxLayout layout;
13 layout.addWidget(&textEdit);
14 layout.addWidget(&quitButton);
15
16 QWidget window;
17 window.setLayout(&layout);
18
19 window.show();
20
21 return app.exec();
22 }
Simple stuff, I would suppose. Upon writing this code in Visual Studio Express 2010, building, and running, most everything works. However, when I try to close the window by means of the "Quit" button or the red-x in the top right of the displayed window (initiating "return app.exec()"), I receive the following:
A dialog box saying,
Unhandled exception at 0x77bc15de in ParticleTracker.exe: 0xC0000005: Access violation reading location 0xdf94b4b4.
And console output saying,
Critical error detected c0000374
Windows has triggered a breakpoint in ParticleTracker.exe.
This may be due to a corruption of the heap, which indicates a bug in ParticleTracker.exe or any of the DLLs it has loaded.
This may also be due to the user pressing F12 while ParticleTracker.exe has focus.
Having entered the debug-mode, I continued through the call stack while repeatedly receiving heap corruption errors.
First-chance exception at 0x77c6e6c3 in ParticleTracker.exe: 0xC0000374: A heap has been corrupted.
Unhandled exception at 0x77bc15de in ParticleTracker.exe: 0xC0000374: A heap has been corrupted.
All of the subsequent exceptions occurred at 0x77bc15de in the executable, with the memory address 0xC0000374 as a corrupted heap.
Honestly, I'm not precisely sure how I could even be getting this issue; I'm not well-versed in C++, but there appears to be nothing wrong with the code.
In the Call-Stack, the process is currently stuck at:
ParticleTracker.exe!main(int argv, char** args) Line 20 + 0x27 bytes
If I enter the disassembly the process is stuck at:
return app.exec();
00FE3831 mov esi,esp
00FE3833 call dword ptr [__imp_QApplication::exec (0FE93D0h)]
00FE3839 cmp esi,esp
00FE383B call #ILT+320(__RTC_CheckEsp) (0FE1145h)
00FE3840 mov dword ptr [ebp-150h],eax
00FE3846 mov byte ptr [ebp-4],5
00FE384A mov esi,esp
00FE384C lea ecx,[ebp-84h]
00FE3852 call dword ptr [__imp_QWidget::~QWidget (0FE9404h)]
00FE3858 cmp esi,esp
Any tips? Much appreciated. :)
Try this one
#include <QtGui>
int main(int argv, char **args)
{
QApplication app(argv, args);
QTextEdit *textEdit = new QTextEdit();
QPushButton *quitButton = new QPushButton("Quit");
QObject::connect(quitButton, SIGNAL(clicked()), qApp, SLOT(quit()));
QVBoxLayout *layout = new QVBoxLayout();
layout->addWidget(textEdit);
layout->addWidget(quitButton);
QWidget *window = new QWidget();
window->setLayout(layout);
window->show();
return app.exec();
}
It might be about ownership. When a widget is destroyed, it also takes care of its children, in your case, layouts and child widgets. QWidget destructior tries to destruct the objects, but they were allocated on the stack, and not dynamically.
Try to use dynamic allocation for QLayouts and widgets.
After googling around I found out that segmentation faults are given when the program is pointed to use memory that it doesn’t have access to.
I’ve recently started experiencing these errors after I tried making a custom button class that would enclose, in its clicked() signal, an integer.
Here’s the custom button class:
.h:
#include <QtGui>
#ifndef CUSTOMBUTTON_H
#define CUSTOMBUTTON_H
class CustomButton : public QPushButton //This simple class allows us to map arguments in the Widget's cicked() signal.
{ //In the project, it's used in the delete-edit buttons so the program knows which part of the Movie/Theater/Screening list we're referring to
Q_OBJECT
public:
CustomButton(QString name,int num, QWidget *parent = 0);
signals:
void clicked(int pos);
private:
QSignalMapper *signalMapper;
};
#endif // CUSTOMBUTTON_H
.cpp:
#include "custombutton.h"
CustomButton::CustomButton(QString name,int num = 0, QWidget *parent) //Our constructor
: QPushButton(name,parent)
{ //Our button's now created and shown, through the superconstructor. Let's take care of its clicked() signal.
signalMapper = new QSignalMapper(this);
connect(this, SIGNAL(clicked()), signalMapper, SLOT(map()));
signalMapper->setMapping(this, num);
connect(signalMapper, SIGNAL(mapped(int)),this, SIGNAL(clicked(int)));
}
And then in my main code I do:
CustomButton *edit_button = new CustomButton("Edit",i,0);
edit_button->setFixedWidth(30);
connect(edit_button,SIGNAL(clicked(int)),this,SLOT(edit_movie(int))); //When the user decides to edit a movie, we set the class'es working_with var to the position of the film in the MovieList and we set the screen to the appropriate one.
CustomButton *del_button = new CustomButton("Delete",i,0); //We pass i as an argument to the button, so it can relate to the movie it's set next to.
del_button->setFixedWidth(45);
connect(del_button,SIGNAL(clicked(int)),this,SLOT(del_movie(int)));
Where i is the number I want it to have in the signal.
Thing is, thorugh the debugger it doesn’t give me a segfault if I press the Delete button. It all happens in the edit one.
As I’m still pretty confused and in a situation where I don’t even know WHAT to ask about, if you need anything else from me please say so and I will provide.
Here’s the backtrace, which I know not how to read:
0 QHash<QObject*, QString>::findNode qhash.h 884 0×69e98594
1 QHash<QObject*, QString>::contains qhash.h 874 0×69e98568
2 QSignalMapper::map qsignalmapper.cpp 267 0×69debe0c
3 QSignalMapper::map qsignalmapper.cpp 257 0×69debda2
4 QSignalMapper::qt_static_metacall moc_qsignalmapper.cpp 64 0×69debfce
5 QMetaObject::activate qobject.cpp 3547 0×69de9baf
6 QAbstractButton::clicked moc_qabstractbutton.cpp 220 0×10cb4b8
7 QAbstractButtonPrivate::emitClicked qabstractbutton.cpp 548 0xe2e517
8 QAbstractButtonPrivate::click qabstractbutton.cpp 541 0xe2e495
9 QAbstractButton::mouseReleaseEvent qabstractbutton.cpp 1123 0xe2f941
10 QWidget::event qwidget.cpp 8362 0xae63de
11 QAbstractButton::event qabstractbutton.cpp 1082 0xe2f7cc
12 QPushButton::event qpushbutton.cpp 683 0xecfeba
13 QApplicationPrivate::notify_helper qapplication.cpp 4554 0xa9c020
14 QApplication::notify qapplication.cpp 4097 0xa9a26a
15 QCoreApplication::notifyInternal qcoreapplication.cpp 876 0×69dd3b76
16 QCoreApplication::sendSpontaneousEvent qcoreapplication.h 234 0×113137e
17 QApplicationPrivate::sendMouseEvent qapplication.cpp 3163 0xa98ad6
18 QETWidget::translateMouseEvent qapplication_win.cpp 3363 0xb03171
19 QtWndProc qapplication_win.cpp 1696 0xafdf66
20 USER32!IsDialogMessageW C:\Windows\syswow64\user32.dll 0 0×76726238
21 USER32!RegisterSystemThread C:\Windows\syswow64\user32.dll 0 0×767278b0
22 ?? 0 0×30000
23 USER32!AllowForegroundActivation C:\Windows\syswow64\user32.dll 0 0×767268ea
24 qt_is_translatable_mouse_event qapplication_win.cpp 1463 0xafd465
25 USER32!GetMessageExtraInfo C:\Windows\syswow64\user32.dll 0 0×76727d31
26 ?? 0
Any heads up as to what might be causing the problem? As I said, the segfault only occurs if I run the program through the Debugger and when I press the "Edit" button, of the CustomButton class. When I normally build&run, the program works 9/10 times. Sometimes, clicking the edit button results in a crash. This erratic behaviour is what caused me to look for help here.
As when I click the button I'm taken to a new screen, I'm suspecting that the problem might lie in the decstructor? Does a blank destructor correctly deconstruct elements of objects of the CustomButton class, seeing as the actual object is passed to the base class constructor? Maybe I've got a leak there?
Unless knowing where you create the objects, it's hard to tell why there is a segfault in QSignalMapper. The pointer to your signal mapper might be invalid at some point in time, so there might be an unwanted deletion.
In some cases, a complete rebuild of your application might be helpful. Also re-running qmake. Just should be on your checklist when you can't explain why there is a segfault ...;)
There is an alternative to QSignalMapper: keep your signal clicked(int) and implement a private slot:
private slots:
this_clicked() {
emit clicked(num);
}
Then put in the constructor:
connect(this, SIGNAL(clicked()), SLOT(this_clicked()));