Solved macOS qt application crash on return of qapplication().exec
-
I have been running this qt program which I wrote the other day smoothly for months.
The qt program read a data file and do some analysis and plotting. It is more like a gui client because the analysis part can be detached as a standalone c program.
However when the program read some file, it crashed. So usually the bug is coming from the analysis part, however the standalone c program on that file still runs smoothly.
so I lldb the program, and found it crashed on the last step, the return of the QApplication.
main.cpp:
#include "mainwindow.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow *w; if (argc > 1) { w =new MainWindow(0,argv[1]); } else { w =new MainWindow(0,""); } w->show(); return a.exec(); }
lldb:
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1 frame #0: 0x000000010000461d kato_qt`main(argc=2, argv=0x00007ffeefbff928) at main.cpp:18:5 15 w =new MainWindow(0,""); 16 } 17 -> 18 w->show(); ^ 19 20 21 return a.exec(); Target 0: (kato_qt) stopped. (lldb) n Process 2352 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = step over frame #0: 0x000000010000462b kato_qt`main(argc=2, argv=0x00007ffeefbff928) at main.cpp:19:12 16 } 17 18 w->show(); -> 19 ^ 20 21 return a.exec(); 22 } Target 0: (kato_qt) stopped. (lldb) n Process 2352 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0xaffffffed) frame #0: 0x0000000100dc6126 QtGui`QFont::~QFont() + 22 QtGui`QFont::~QFont: -> 0x100dc6126 <+22>: lock 0x100dc6127 <+23>: decl (%rax) 0x100dc6129 <+25>: jne 0x100dc61dc ; <+204> 0x100dc612f <+31>: movq (%rdi), %r14 Target 0: (kato_qt) stopped. (lldb) bt * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0xaffffffed) * frame #0: 0x0000000100dc6126 QtGui`QFont::~QFont() + 22 frame #1: 0x000000010069a403 QtWidgets`QRenderRule::~QRenderRule() + 547 frame #2: 0x0000000101545b39 QtCore`QHashData::free_helper(void (*)(QHashData::Node*)) + 73 frame #3: 0x0000000101545b39 QtCore`QHashData::free_helper(void (*)(QHashData::Node*)) + 73 frame #4: 0x00000001006854d1 QtWidgets`QHash<QObject const*, QHash<int, QHash<unsigned long long, QRenderRule> > >::remove(QObject const* const&) + 321 frame #5: 0x0000000100685c59 QtWidgets`QStyleSheetStyle::polish(QWidget*) + 313 frame #6: 0x0000000100620426 QtWidgets`QWidget::event(QEvent*) + 3142 frame #7: 0x00000001006c7aad QtWidgets`QFrame::event(QEvent*) + 45 frame #8: 0x00000001005e4f5a QtWidgets`QApplicationPrivate::notify_helper(QObject*, QEvent*) + 266 frame #9: 0x00000001005e63e6 QtWidgets`QApplication::notify(QObject*, QEvent*) + 598 frame #10: 0x00000001016d99f4 QtCore`QCoreApplication::notifyInternal2(QObject*, QEvent*) + 212 frame #11: 0x000000010061374b QtWidgets`QWidget::ensurePolished() const + 75 frame #12: 0x00000001006137f1 QtWidgets`QWidget::ensurePolished() const + 241 frame #13: 0x000000010061fdfd QtWidgets`QWidget::event(QEvent*) + 1565 frame #14: 0x00000001005e4f5a QtWidgets`QApplicationPrivate::notify_helper(QObject*, QEvent*) + 266 frame #15: 0x00000001005e63e6 QtWidgets`QApplication::notify(QObject*, QEvent*) + 598 frame #16: 0x00000001016d99f4 QtCore`QCoreApplication::notifyInternal2(QObject*, QEvent*) + 212 frame #17: 0x00000001016dabe9 QtCore`QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) + 809 frame #18: 0x00000001055b90e9 libqcocoa.dylib`QCocoaEventDispatcherPrivate::processPostedEvents() + 313 frame #19: 0x00007fff32dfb4f5 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23 frame #20: 0x00007fff32dfb427 CoreFoundation`__CFRunLoopDoObservers + 457 frame #21: 0x00007fff32df9fa4 CoreFoundation`CFRunLoopRunSpecific + 372 frame #22: 0x00007fff31a2dabd HIToolbox`RunCurrentEventLoopInMode + 292 frame #23: 0x00007fff31a2d6f4 HIToolbox`ReceiveNextEventCommon + 359 frame #24: 0x00007fff31a2d579 HIToolbox`_BlockUntilNextEventMatchingListInModeWithFilter + 64 frame #25: 0x00007fff30078c99 AppKit`_DPSNextEvent + 883 frame #26: 0x00007fff300774e0 AppKit`-[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 1352 frame #27: 0x00007fff300691ee AppKit`-[NSApplication run] + 658 frame #28: 0x00000001055b85d3 libqcocoa.dylib`QCocoaEventDispatcher::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) + 2579 frame #29: 0x00000001016d5a7f QtCore`QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) + 431 frame #30: 0x00000001016da002 QtCore`QCoreApplication::exec() + 130 frame #31: 0x0000000100004630 kato_qt`main(argc=2, argv=0x00007ffeefbff928) at main.cpp:19:12 frame #32: 0x00007fff6cd42cc9 libdyld.dylib`start + 1 frame #33: 0x00007fff6cd42cc9 libdyld.dylib`start + 1
if I run the program in console again, a full Mac crash report is as the following
system Integrity Protection: enabled Crashed Thread: 0 Dispatch queue: com.apple.main-thread Exception Type: EXC_BAD_ACCESS (SIGSEGV) Exception Codes: KERN_INVALID_ADDRESS at 0x0000002700000007 Exception Note: EXC_CORPSE_NOTIFY Termination Signal: Segmentation fault: 11 Termination Reason: Namespace SIGNAL, Code 0xb Terminating Process: exc handler [2517] VM Regions Near 0x2700000007: __LINKEDIT 00000001a5e10000-00000001a5e13000 [ 12K] rw-/rwx SM=NUL /usr/lib/libobjc-trampolines.dylib --> STACK GUARD 000070000f549000-000070000f54a000 [ 4K] ---/rwx SM=NUL stack guard for thread 1 Thread 0 Crashed:: Dispatch queue: com.apple.main-thread 0 org.qt-project.QtGui 0x000000010cfb1f6e QPainterPath::~QPainterPath() + 14 1 org.qt-project.QtWidgets 0x000000010c69f1f6 QRenderRule::~QRenderRule() + 22 2 org.qt-project.QtCore 0x000000010d55cb39 QHashData::free_helper(void (*)(QHashData::Node*)) + 73 3 org.qt-project.QtCore 0x000000010d55cb39 QHashData::free_helper(void (*)(QHashData::Node*)) + 73 4 org.qt-project.QtWidgets 0x000000010c68a4d1 QHash<QObject const*, QHash<int, QHash<unsigned long long, QRenderRule> > >::remove(QObject const* const&) + 321 5 org.qt-project.QtWidgets 0x000000010c68ac59 QStyleSheetStyle::polish(QWidget*) + 313 6 org.qt-project.QtWidgets 0x000000010c625426 QWidget::event(QEvent*) + 3142 7 org.qt-project.QtWidgets 0x000000010c6ccaad QFrame::event(QEvent*) + 45 8 org.qt-project.QtWidgets 0x000000010c5e9f5a QApplicationPrivate::notify_helper(QObject*, QEvent*) + 266 9 org.qt-project.QtWidgets 0x000000010c5eb3e6 QApplication::notify(QObject*, QEvent*) + 598 10 org.qt-project.QtCore 0x000000010d6f09f4 QCoreApplication::notifyInternal2(QObject*, QEvent*) + 212 11 org.qt-project.QtWidgets 0x000000010c61874b QWidget::ensurePolished() const + 75 12 org.qt-project.QtWidgets 0x000000010c6187f1 QWidget::ensurePolished() const + 241 13 org.qt-project.QtWidgets 0x000000010c624dfd QWidget::event(QEvent*) + 1565 14 org.qt-project.QtWidgets 0x000000010c5e9f5a QApplicationPrivate::notify_helper(QObject*, QEvent*) + 266 15 org.qt-project.QtWidgets 0x000000010c5eb3e6 QApplication::notify(QObject*, QEvent*) + 598 16 org.qt-project.QtCore 0x000000010d6f09f4 QCoreApplication::notifyInternal2(QObject*, QEvent*) + 212 17 org.qt-project.QtCore 0x000000010d6f1be9 QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) + 809 18 libqcocoa.dylib 0x000000010f4c10e9 QCocoaEventDispatcherPrivate::processPostedEvents() + 313 19 com.apple.CoreFoundation 0x00007fff32dfb4f5 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23 20 com.apple.CoreFoundation 0x00007fff32dfb427 __CFRunLoopDoObservers + 457 21 com.apple.CoreFoundation 0x00007fff32df9fa4 CFRunLoopRunSpecific + 372 22 com.apple.HIToolbox 0x00007fff31a2dabd RunCurrentEventLoopInMode + 292 23 com.apple.HIToolbox 0x00007fff31a2d6f4 ReceiveNextEventCommon + 359 24 com.apple.HIToolbox 0x00007fff31a2d579 _BlockUntilNextEventMatchingListInModeWithFilter + 64 25 com.apple.AppKit 0x00007fff30078c99 _DPSNextEvent + 883 26 com.apple.AppKit 0x00007fff300774e0 -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 1352 27 com.apple.AppKit 0x00007fff300691ee -[NSApplication run] + 658 28 libqcocoa.dylib 0x000000010f4c05d3 QCocoaEventDispatcher::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) + 2579 29 org.qt-project.QtCore 0x000000010d6eca7f QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) + 431 30 org.qt-project.QtCore 0x000000010d6f1002 QCoreApplication::exec() + 130 31 illya.co.kato-qt 0x000000010c105630 main + 256 (main.cpp:21) 32 libdyld.dylib 0x00007fff6cd42cc9 start + 1 Thread 1: 0 libsystem_pthread.dylib 0x00007fff6cf42b68 start_wqthread + 0 Thread 2: 0 libsystem_pthread.dylib 0x00007fff6cf42b68 start_wqthread + 0 Thread 3: 0 libsystem_pthread.dylib 0x00007fff6cf42b68 start_wqthread + 0 Thread 4: 0 libsystem_pthread.dylib 0x00007fff6cf42b68 start_wqthread + 0 Thread 0 crashed with X86 Thread State (64-bit): rax: 0x0000000000000007 rbx: 0x0000002700000007 rcx: 0x0000000000000001 rdx: 0x000000000000001a rdi: 0x00007fc4ed5b4590 rsi: 0x000000010c6a2820 rbp: 0x00007ffee3afd3f0 rsp: 0x00007ffee3afd3e0 r8: 0x000000000000001a r9: 0x0000000000000001 r10: 0x00007fc4ed500000 r11: 0x0000000000000000 r12: 0x00007fc4ed5b4130 r13: 0x00007fc4ed5b4478 r14: 0x000000010c6a2820 r15: 0x00007fc4ed5b4130 rip: 0x000000010cfb1f6e rfl: 0x0000000000010202 cr2: 0x0000002700000007 Logical CPU: 2 Error Code: 0x00000006 (no mapping for user data write) Trap Number: 14
really weird.
-
Hi and welcome to devnet,
One thing that is not nice is that you are not explicitly freeing your widget before finishing your application. Therefore you are not releasing properly the resources that you allocated through it.
Since you may have an argument passed to your application, I would recommend using QCommandLineParser to handle your argument. Give it an empty string as default value so you don't have to create your widget on the heap and thus you won't have to delete explicitly.
Not that even now, you can avoid that by handling the parameter in your if and creating your widget after.
-
This post is deleted! -
@SGaist said in macOS qt application crash on return of qapplication().exec:
QCommandLineParser
thank you for the quick reply.
I will try to modify the code to test it again.
I never thought passing a char array parameter will change the program's heap and stack behavior on MainWindow().
-
I am back, I quickly copy pasted the QCommandLineParser sample, and modify the code to make EVERY newed class contains no char array argument. failed again.
Then I explicitly freed every newed object in every destruction method. failed.
still this gui qt program on data file X failed and all the other data file succeeded.
the core non-gui c program succeeded on all the data files.
lldb again proved this:
main.cpp:
#include "mainwindow.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication app(argc, argv); QApplication::setApplicationName("kato_qt"); QApplication::setApplicationVersion("2.0"); QCommandLineParser parser; parser.setApplicationDescription("a gui client for kato_core"); parser.addHelpOption(); parser.addVersionOption(); parser.addPositionalArgument("datafile", QApplication::translate("main", "data file to import.")); parser.addOptions({ // A boolean option with a single name (-p) {"p", QApplication::translate("main", "Show progress during copy")}, // A boolean option with multiple names (-f, --force) {{"f", "force"}, QApplication::translate("main", "Overwrite existing files.")}, // An option with a value {{"t", "target-directory"}, QApplication::translate("main", "Copy all source files into <directory>."), QApplication::translate("main", "directory")}, }); parser.process(app); const QStringList args = parser.positionalArguments(); // data file is args.at(0) bool showProgress = parser.isSet("p"); bool force = parser.isSet("f"); QString targetDir = parser.value("t"); if (args.size() < 1) { parser.showHelp(); } else { MainWindow *w = new MainWindow(0); w->datafile = args.at(0); w->setWindow(); w->show(); } return app.exec(); }
lldb result:
(lldb) b main.cpp:50 Breakpoint 1: where = kato_qt`main + 3363 at main.cpp:51:10, address = 0x0000000100005ff3 (lldb) r There is a running process, kill it and restart?: [Y/n] Y Process 8316 exited with status = 9 (0x00000009) Process 8357 launched: '/Users/yuanchuan/Code/qt/kato_qt/production/Debug/kato_qt.app/Contents/MacOS/kato_qt' (x86_64) 2020-05-03 22:37:34.514365+0800 kato_qt[8357:294724] opengl worked on pswidget.cpp 2020-05-03 22:37:34, databox_run_file_quote5, datafile = /Users/yuanchuan/Downloads/data/ag2006_3_5 2020-05-03 22:37:34, databox_run_file_quote5, IF_MONITOR_COMPILED = 1 2020-05-03 22:37:34, databox_run_file_quote5, IF_MA_COMPILED = 1 2020-05-03 22:37:34, databox_run_file_quote5, IF_CHANNEL_COMPILED = 1 2020-05-03 22:37:34, databox_run_file_quote5, IF_TICK_GROUP_COMPILED = 0 2020-05-03 22:37:34, databox_run_file_quote5, IF_TRADE_COMPILED = 1 2020-05-03 22:37:34, databox_run_file_quote5, IF_TREND_COMPILED = 1 2020-05-03 22:37:34, databox_run_file_quote5, IF_ORDER_BOOK_COMPILED = 1 2020-05-03 22:37:34, databox_run_file_quote5, TREND_COUNT = 5 2020-05-03 22:37:34, databox_run_file_quote5, QUOTE_SIZE = 5 2020-05-03 22:37:34, databox_run_file_quote5, MAX_DB_SIZE = 1500000 total 139821 / 139854 data imported import data avg: 1.71 microsec before trade avg: 1.05 microsec after trade avg: 2.85 microsec 2020-05-03 22:37:35.438822+0800 kato_qt[8357:294724] ma para: 900 2400 2020-05-03 22:37:35.438839+0800 kato_qt[8357:294724] channel para: 5 120 Process 8357 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1 frame #0: 0x0000000100005ff3 kato_qt`main(argc=2, argv=0x00007ffeefbff928) at main.cpp:51:10 48 w->show(); 49 } 50 -> 51 return app.exec(); ^ 52 } Target 0: (kato_qt) stopped. (lldb) s Process 8357 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x4600000196) frame #0: 0x0000000100fadf6e QtGui`QPainterPath::~QPainterPath() + 14 QtGui`QPainterPath::~QPainterPath: -> 0x100fadf6e <+14>: lock 0x100fadf6f <+15>: decl (%rbx) 0x100fadf71 <+17>: jne 0x100fadf89 ; <+41> 0x100fadf73 <+19>: movq %rbx, %rdi Target 0: (kato_qt) stopped. (lldb) bt * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x4600000196) * frame #0: 0x0000000100fadf6e QtGui`QPainterPath::~QPainterPath() + 14 frame #1: 0x00000001006a41f6 QtWidgets`QRenderRule::~QRenderRule() + 22 frame #2: 0x000000010154fb39 QtCore`QHashData::free_helper(void (*)(QHashData::Node*)) + 73 frame #3: 0x000000010154fb39 QtCore`QHashData::free_helper(void (*)(QHashData::Node*)) + 73 frame #4: 0x000000010068f4d1 QtWidgets`QHash<QObject const*, QHash<int, QHash<unsigned long long, QRenderRule> > >::remove(QObject const* const&) + 321 frame #5: 0x000000010068fc59 QtWidgets`QStyleSheetStyle::polish(QWidget*) + 313 frame #6: 0x000000010062a426 QtWidgets`QWidget::event(QEvent*) + 3142 frame #7: 0x00000001006d1aad QtWidgets`QFrame::event(QEvent*) + 45 frame #8: 0x00000001005eef5a QtWidgets`QApplicationPrivate::notify_helper(QObject*, QEvent*) + 266 frame #9: 0x00000001005f03e6 QtWidgets`QApplication::notify(QObject*, QEvent*) + 598 frame #10: 0x00000001016e39f4 QtCore`QCoreApplication::notifyInternal2(QObject*, QEvent*) + 212 frame #11: 0x000000010061d74b QtWidgets`QWidget::ensurePolished() const + 75 frame #12: 0x000000010061d7f1 QtWidgets`QWidget::ensurePolished() const + 241 frame #13: 0x0000000100629dfd QtWidgets`QWidget::event(QEvent*) + 1565 frame #14: 0x00000001005eef5a QtWidgets`QApplicationPrivate::notify_helper(QObject*, QEvent*) + 266 frame #15: 0x00000001005f03e6 QtWidgets`QApplication::notify(QObject*, QEvent*) + 598 frame #16: 0x00000001016e39f4 QtCore`QCoreApplication::notifyInternal2(QObject*, QEvent*) + 212 frame #17: 0x00000001016e4be9 QtCore`QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) + 809 frame #18: 0x0000000105ac20e9 libqcocoa.dylib`QCocoaEventDispatcherPrivate::processPostedEvents() + 313 frame #19: 0x00007fff32dfb4f5 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23 frame #20: 0x00007fff32dfb427 CoreFoundation`__CFRunLoopDoObservers + 457 frame #21: 0x00007fff32df9fa4 CoreFoundation`CFRunLoopRunSpecific + 372 frame #22: 0x00007fff31a2dabd HIToolbox`RunCurrentEventLoopInMode + 292 frame #23: 0x00007fff31a2d6f4 HIToolbox`ReceiveNextEventCommon + 359 frame #24: 0x00007fff31a2d579 HIToolbox`_BlockUntilNextEventMatchingListInModeWithFilter + 64 frame #25: 0x00007fff30078c99 AppKit`_DPSNextEvent + 883 frame #26: 0x00007fff300774e0 AppKit`-[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 1352 frame #27: 0x00007fff300691ee AppKit`-[NSApplication run] + 658 frame #28: 0x0000000105ac15d3 libqcocoa.dylib`QCocoaEventDispatcher::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) + 2579 frame #29: 0x00000001016dfa7f QtCore`QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) + 431 frame #30: 0x00000001016e4002 QtCore`QCoreApplication::exec() + 130 frame #31: 0x0000000100005ff8 kato_qt`main(argc=2, argv=0x00007ffeefbff928) at main.cpp:51:10 frame #32: 0x00007fff6cd42cc9 libdyld.dylib`start + 1 frame #33: 0x00007fff6cd42cc9 libdyld.dylib`start + 1 (lldb)
-
Something is strange here. You added the QCommandLine parser yet you are not really using. Why ?
-
In fact I am using it and the QCommandLine parser worked.
because I passed the parameter thru the lldb command line like
lldb -o run -- ./.../kato_qt datafile
so during the lldb process, I only need to send 'r' to easily restart the program with parameter again.
and I am using the usual way to check it again, the error still showed.
and if the file parameter is not sent in, the help() will be shown,
if the datafile is broken or can not be found, it will all be recored in the log, however, the core process finished
successfully as you can see "import before after..." stuff in the log, and lldb came to the last line of the program without exiting.so heap and stack stuff: the huge data struct is a private member of a class, and explicitly predefined in a c style, in a fixed number of array, as you can see in the log MAX_DB_SIZE. and this datafile X is really small, only 100k, compared to some other successful processed file, 1 million.
so the strange thing is the bug seemed to depend on the parameter sent in, but lldb and every other logic showed it is not.
ok, I choose not to trust lldb, and hard coded style debugging
main.cpp as above.
next is the setup function in mainwindow.cpp:void MainWindow::setWindow() { move (1000,1000); resize(1700,800); #ifndef Q_OS_DARWIN setWindowIcon(QIcon(":/resources/favicon.ico")); #endif setWindowTitle(local2qstr("かとう めぐみ")); myPS = new psWidget(this); myPS->fname = datafile; setCentralWidget(myPS); myPS->start(); }
now we come to the center setup function in the start() method in pswidget.cpp
void psWidget::start() { databox_init (&med, db); // databox_run_file_quote5 (db, &med, // fname.toStdString().c_str()); // onRequestPlotData(); }
med and db are structs stored as private member of the class. db are on the stack. med is rather small.
here is the result:
On datafile X:
-
commented out the
onRequestPlotData()
: same bug, and output log showeddatabox_run_file_quote5
successfully returned -
commented out the
onRequestPlotData()
&databox_run_file_quote5
: success -
I have another c project with all the same c files, in the main function there are only the same two lines:
databox_init
&data box_run_file_quote5
: success, and memory leaks free (checked byleaks
)
On all the other datafiles, some one is much bigger: all good.
so the strange thing is the bug seemed to depend on the datafile sent in, or in the
databox_run_file_quote5
but lldb and every other logic showed it is not.
ok I don't trust macOS and lldb now,
I switched to archlinux and gdb. and it turned out that the standalone c core program failed on that X file too. so it is pretty much sure that this issue is not coming from qt, I messed up got some heap corruption there.
thanks for all the help and suggestion. this issue can be marked as solved.
-
-
You're welcome !
To mark the issue as solved, you can either use the "Topic Tools" button or the three doted menu beside the answer you deem correct.