Qt6 Android app crashes on Redmi Note 8 Pro when QDialog is accepted
-
Hi everyone,
I have a Qt 6 Android application that works fine on most devices (Samsung S22, Redmi Note 8, Emulator), but crashes on Redmi Note 8 Pro when I open a QDialog (like NewDevice) and press the Save button.
Here’s a simplified overview of my setup:
main.cpp
#include "anapencere.h" #include <QApplication> #include <QLocale> #include <QTranslator> #include "veri/veritabani.h" #include <QStyleHints> void applySystemTheme() { Qt::ColorScheme scheme = qApp->styleHints()->colorScheme(); QString themeFile; if (scheme == Qt::ColorScheme::Dark) themeFile = ":/themes/dark.qss"; else themeFile = ":/themes/light.qss"; QFile file(themeFile); if (file.open(QFile::ReadOnly | QFile::Text)) qApp->setStyleSheet(file.readAll()); } int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_UseSoftwareOpenGL); QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts); QApplication a(argc, argv); applySystemTheme(); QObject::connect(qApp->styleHints(), &QStyleHints::colorSchemeChanged, qApp, [](){ applySystemTheme(); }); veritabani::vt().load(); anapencere w; w.show(); auto sonuc = a.exec(); veritabani::vt().save(); return sonuc; }anapencere.cpp (Main Window)
anapencere::anapencere(QWidget *parent) : QMainWindow(parent) , ui(new Ui::anapencere) { ui->setupUi(this); this->showMaximized(); this->setFocusPolicy(Qt::StrongFocus); this->setFocus(); qApp->installEventFilter(this); //Devices ui->leDevicesSearch->installEventFilter(this); ui->tblwgDevices->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); ui->tblwgDevices->horizontalHeader()->setStretchLastSection(true); ui->tblwgDevices->verticalHeader()->setVisible(false); ui->tblwgDevices->setEditTriggers(QAbstractItemView::NoEditTriggers); ui->tblwgDevices->setSelectionBehavior(QAbstractItemView::SelectRows); ui->btnNewComp->setObjectName("primaryButton"); ui->btnNewDevice->setObjectName("primaryButton"); connect(ui->tblwgDevices,&QTableWidget::itemSelectionChanged,this,&anapencere::devtblwSecim); searchTimer1 = new QTimer(this); searchTimer1->setSingleShot(true); connect(ui->leDevicesSearch, &QLineEdit::textChanged, this, [this](){ searchTimer1->start(500); }); connect(searchTimer1, &QTimer::timeout, this, &anapencere::devsearch); //Components ui->leCompSearch->installEventFilter(this); ui->tblwgComp->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); ui->tblwgComp->horizontalHeader()->setStretchLastSection(true); ui->tblwgComp->verticalHeader()->setVisible(false); ui->tblwgComp->setEditTriggers(QAbstractItemView::NoEditTriggers); ui->tblwgComp->setSelectionBehavior(QAbstractItemView::SelectRows); connect(ui->tblwgComp,&QTableWidget::itemSelectionChanged,this,&anapencere::comptblwSecim); searchTimer2 = new QTimer(this); searchTimer2->setSingleShot(true); connect(ui->leCompSearch, &QLineEdit::textChanged, this, [this](){ searchTimer2->start(500); }); connect(searchTimer2, &QTimer::timeout, this, &anapencere::compsearch); } void anapencere::showMessage(QMessageBox::Icon icon, const QString &title, const QString &text) { if (QWidget *focused = qApp->focusWidget()) { focused->clearFocus(); } QTimer::singleShot(150, this, [=]() { QMessageBox *msg = new QMessageBox(icon, title, text, QMessageBox::Ok, this); msg->setAttribute(Qt::WA_DeleteOnClose); msg->open(); }); } bool anapencere::eventFilter(QObject *obj, QEvent *event) { if (qApp->activeModalWidget() != nullptr || qApp->activeWindow() != this) { return QObject::eventFilter(obj, event); } if (qobject_cast<QLineEdit*>(obj)) { return QObject::eventFilter(obj, event); } if (event->type() == QEvent::KeyPress) { QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event); if (keyEvent->key() == Qt::Key_Backspace) { return QObject::eventFilter(obj, event); } if (keyEvent->key() == Qt::Key_Back || keyEvent->key() == Qt::Key_Escape) { if (ui->stackedWidget->currentIndex() != 0) { back(); return true; } else { QMessageBox *msg = new QMessageBox(QMessageBox::Question, "Çıkış", "Uygulamadan çıkmak istiyor musunuz?", QMessageBox::NoButton, this); QPushButton *evetButonu = msg->addButton("Evet", QMessageBox::YesRole); msg->addButton("Hayır", QMessageBox::NoRole); connect(msg, &QMessageBox::buttonClicked, this, [=](QAbstractButton *btn){ if (btn == evetButonu) QCoreApplication::quit(); }); msg->setAttribute(Qt::WA_DeleteOnClose); msg->open(); return true; } } } return QObject::eventFilter(obj, event); } //... other code void anapencere::on_btnNewDevice_clicked() { NewDevice *frm = new NewDevice(this); frm->setAttribute(Qt::WA_DeleteOnClose); auto device = veritabani::vt().devices()._new(); frm->setData(device); connect(frm, &QDialog::accepted, this, [=]() { *device = *frm->getData(); auto existing = veritabani::vt().devices().search([device](DeviceTable::VeriPointer d){ return d->getSerialnumber().toLower() == device->getSerialnumber().toLower(); }); if (!existing.isEmpty()) { showMessage(QMessageBox::Critical, "Error", QString("%1 serial number already exists!").arg(device->getSerialnumber())); return; } veritabani::vt().devices().add(device); veritabani::vt().save(); showMessage(QMessageBox::Information, "Info", QString("%1 device added.").arg(device->getSerialnumber())); devsearch(); }); frm->open(); // Using open() instead of exec() }anapencere.h (MainWindow)
#pragma once #include "veri/veritabani.h" #include <QMainWindow> #include <QTimer> #include "ui/editcomponent.h" #include "ui/editdevice.h" #include "ui/newcomponent.h" #include "ui/newdevice.h" #include "ui/repairtasks.h" #include <qevent.h> #include <QMessageBox> QT_BEGIN_NAMESPACE namespace Ui { class anapencere; } QT_END_NAMESPACE class anapencere : public QMainWindow { Q_OBJECT public: anapencere(QWidget *parent = nullptr); ~anapencere(); void devicesload(); void devsearch(); void devtblwSecim(); void compload(); void compsearch(); void comptblwSecim(); void showMessage(QMessageBox::Icon icon, const QString &title, const QString &text); protected: bool eventFilter(QObject *obj, QEvent *event) override; void back(); private slots: void on_btnDevices_clicked(); void on_btnComp_clicked(); void on_btnRepairTask_clicked(); void on_btnNewDevice_clicked(); void on_btnDevicesEdit_clicked(); void on_btnDevicesDel_clicked(); void on_btnCompEdit_clicked(); void on_btnCompDel_clicked(); void on_btnNewComp_clicked(); void on_btnBack_clicked(); void on_btnBack2_clicked(); private: Ui::anapencere *ui; QTimer *searchTimer1; QTimer *searchTimer2; DeviceTable::VeriListesi deviceslist; ComponentTable::VeriListesi complist; };NewDevice.cpp QDialog
#include "newdevice.h" #include "ui/ui_newdevice.h" NewDevice::NewDevice(QWidget *parent) : QDialog(parent) , ui(new Ui::NewDevice) { ui->setupUi(this); ui->dteEntryDate->setDateTime(QDateTime::currentDateTime()); ui->btnSave->setObjectName("primaryButton"); } NewDevice::~NewDevice() { delete ui; } DeviceTable::VeriPointer NewDevice::getData() const { data->setSerialnumber(ui->leSerial->text()); data->setModelName(ui->leModel->text()); data->setCustomerName(ui->leCustomer->text()); data->setEntryDate(ui->dteEntryDate->dateTime()); auto n=ui->cbStatus->currentText(); statusenum status; if(n=="Tamirde"){ status = statusenum::Tamirde; }else if(n=="Tamamlandi"){ status = statusenum::Tamamlandi; }else if(n=="Iade"){ status = statusenum::Iade; }else if(n=="Testte"){ status = statusenum::Testte; }else{ status = statusenum::Beklemede; } data->setStatus(status); data->setFaultDescription(ui->teFaultDesc->toPlainText()); return data; } void NewDevice::setData(DeviceTable::VeriPointer newData) { data = newData; ui->leSerial->setText(data->getSerialnumber()); ui->leModel->setText(data->getModelName()); ui->leCustomer->setText(data->getCustomerName()); ui->dteEntryDate->setDateTime(data->getEntryDate()); statusenum status=data->getStatus(); switch (status) { case statusenum::Beklemede: ui->cbStatus->setCurrentText("Beklemede"); break; case statusenum::Iade: ui->cbStatus->setCurrentText("İade"); break; case statusenum::Tamamlandi: ui->cbStatus->setCurrentText("Tamamlandı"); break; case statusenum::Tamirde: ui->cbStatus->setCurrentText("Tamirde"); break; case statusenum::Testte: ui->cbStatus->setCurrentText("Testte"); break; default: ui->cbStatus->setCurrentText("Beklemede"); break; } ui->teFaultDesc->setPlainText(data->getFaultDescription()); } void NewDevice::on_btnSave_clicked() { if (ui->leModel->text().trimmed().isEmpty()) { QMessageBox::warning(this, "Eksik Bilgi", "Lütfen Model Kısmını Boş Geçmeyiniz!"); return; } if (ui->leSerial->text().trimmed().isEmpty()) { QMessageBox::warning(this, "Eksik Bilgi", "Lütfen Seri No Kısmını Boş Geçmeyiniz!"); return; } if (ui->teFaultDesc->toPlainText().trimmed().isEmpty()) { QMessageBox::warning(this, "Eksik Bilgi", "Lütfen Arıza Açıklaması Kısmını Boş Geçmeyiniz!"); return; } QDialog::accept(); }NewDevice.h QDialog
#pragma once #include <QDialog> #include <QMessageBox> #include "../veri/veritabani.h" namespace Ui { class NewDevice; } class NewDevice : public QDialog { Q_OBJECT public: explicit NewDevice(QWidget *parent = nullptr); ~NewDevice(); DeviceTable::VeriPointer getData() const; void setData(DeviceTable::VeriPointer newData); private slots: void on_btnSave_clicked(); private: Ui::NewDevice *ui; DeviceTable::VeriPointer data; };Problem
The app crashes only on Redmi Note 8 Pro when accepting the dialog.
Works fine on Redmi Note 8, Samsung S22, and emulator.
I suspect this could be related to pointer lifetimes, QDialog::open() vs exec(), or device-specific memory issues, but I can’t figure out why it happens only on this device.
The DeviceTable::VeriPointer is stored in the main window after the dialog closes.
Question
Has anyone experienced QDialog crashes on specific Android devices after pressing accept?
Could this be related to heap, pointer lifetime, or CPU architecture differences?
How can I safely debug or prevent this crash on Redmi Note 8 Pro?
Qt and Android Configuration:Qt Version: 6.10.2 Build Kit: Android arm64-v8a Android Build-tools Version: 36.1.0 Android Platform SDK: android-36 Android Customization: NoneDevice Testing:
Samsung S22 : Works correctly. Samsung S9 Fe (tablet) : Works correctly. Android Studio Device Android 16.0 x86_64 : Works correctly. Redmi Note 8: Works correctly. Redmi Note 8 Pro: Crashes -
Hi,
please provide a simple, compilable reproducer.
Yours doesn't compile, because you are using a UI file which is not posted.
It also would make the reproducer too large.My wild guess is that you have a use-after-free, which randomly works when the freed memory hasn't been re-used and crashes when it has been re-used.
Either simplify this further, preferably into one single file.
Or, at least, through debug statements in all your destructors and observe what happens.
Please also provide a stack trace.