QT 5.6.1应用程序仅在x86 arch上退出插槽后崩溃,而不是x64

QT 5.6.1 app crashes after exiting slot only on x86 arch but not x64

本文关键字:崩溃 插槽 x64 退出 应用程序 arch x86 QT      更新时间:2023-10-16

我遇到了一个我无法理解的问题,我需要你的指引。关于我的问题,我还没有找到其他题目的答案。

背景:

  • 我在Windows 10 x64上使用QT 5.6.1动态编译(x86和x64)。

问题:

我编写了一个基本的程序,编译了两次(x86和x64),只显示一个带有按钮的窗口,并将按钮连接到"点击"信号。我的窗口是正确显示的,但是当我点击按钮来触发信号时,应用程序在退出连接到signal的插槽后崩溃了(qDebug从插槽中正确调用)。但我只面对这个问题与x86 QT dll的…

下面是代码:

. cpp:

MyWidget::MyWidget()
{
    QMainWindow *pqMainWindow= new QMainWindow(this);
    QPushButton *pqButton= new QPushButton("MyButton");
    /* Setting up the window */
    pqMainWindow->setWindowModality(Qt::WindowModal);
    pqMainWindow->setGeometry(geometry());
    pqMainWindow->move(QPoint(100, 100));
    /* Connecting signal clicked to slot */
    QObject::connect(pqButton, SIGNAL(clicked(bool)), this, SLOT(_onMyActionTriggered(bool)));    
    pqMainWindow->setCentralWidget(pqButton);
    /* Showing the window */
    pqMainWindow->show();
}
MyWidget::~MyWidget()
{
    /* Nothing to do yet */
}
void MyWidget::_onMyActionTriggered(bool bValue)
{
    qDebug("Slot <_onMyActionTriggered> called");
}
int __cdecl main(int argc, char **argv)
{
    QApplication qapp(argc, argv);
    MyWidget widget;
    return qapp.exec();
}

. h

class MyWidget: public QWidget
{
    Q_OBJECT;
    public:
        MyWidget();
        virtual ~MyWidget();
    private slots:
        void _onMyActionTriggered(bool bValue);
    private:
};
下面是调用跟踪:
Qt5Widgets!QAction::activate+0x103
Qt5Widgets!QToolButton::nextCheckState+0x1a
Qt5Widgets!QAbstractButton::click+0x103
Qt5Widgets!QAbstractButton::mouseReleaseEvent+0x7e
Qt5Widgets!QToolButton::mouseReleaseEvent+0xd
Qt5Widgets!QWidget::event+0xa8
Qt5Widgets!QSizePolicy::QSizePolicy+0x83b
Qt5Core!QCoreApplication::translate+0x30f56
Qt5Gui!QGuiApplicationPrivate::processMouseEvent+0x6c1
USER32!SetManipulationInputTarget+0x53
USER32!DispatchMessageW+0x251
USER32!DispatchMessageW+0x10
qwindows!qt_plugin_query_metadata+0x2065
Qt5Core!QCoreApplication::exec+0x160
qt_auth_test!wmain+0x7c
qt_auth_test!QObject::event+0xb5
KERNEL32!BaseThreadInitThunk+0x24
ntdll!RtlUnicodeStringToInteger+0x21e
ntdll!RtlCaptureContext+0xe1

我自己编译了QT,但在使用QT网站上下载的dll和lib时,我有相同的结果。

谢谢大家的帮助,我终于找到问题了。

答案如下:

我的程序使用stdcall (/Gz)约定,但QT使用cdecl (/Gd)。生成的moc文件是用stdcall约定编译的,这就是导致问题的原因(由于调用者和调用者之间的约定不同,释放参数时出现堆栈问题)。现在我的程序是使用stdcall约定编译的(因为它对我来说是强制性的),但是生成的moc文件是用cdecl编译的,我已经在我的私有槽头上设置了__cdecl关键字!现在它工作完美!

再次感谢您的宝贵时间。

在隐藏小部件的子部件上设置窗口模式是没有意义的。也许这是个问题。尝试以下操作,并检查它是否/何时崩溃。至少在OS X上肯定有一个Qt 5.6的错误:当按钮的模式恢复时,小部件仍然没有接收输入,你必须通过其他方式退出应用程序。

#include <QtWidgets>
int main(int argc, char **argv)
{
   int n = 0;
   QApplication app{argc, argv};
   QPushButton widget{"Widget"};
   QPushButton button{"Button", &widget};
   button.setWindowFlags(Qt::Window);
   QObject::connect(&button, &QPushButton::clicked, [&]{
      button.setText(button.text().append("."));
      ++n;
      if (n == 5) {
         button.setWindowModality(Qt::WindowModal);
         button.hide();
         button.show();
      }
      else if (n == 10) {
         button.setWindowModality(Qt::NonModal);
         button.hide();
         button.show();
      }
      else if (n == 15)
         app.quit();
   });
   button.move(widget.geometry().bottomRight());
   widget.show();
   button.show();
   return app.exec();
}