QT 5.6.1 应用程序在退出插槽后仅在 x86 架构而不是 x64 上崩溃
Posted
技术标签:
【中文标题】QT 5.6.1 应用程序在退出插槽后仅在 x86 架构而不是 x64 上崩溃【英文标题】:QT 5.6.1 app crashes after exiting slot only on x86 arch but not x64 【发布时间】:2016-06-28 13:52:56 【问题描述】:我面临一个我无法理解的问题,我需要你的灯。我还没有找到关于其他主题的问题的答案。
上下文:
我在 Windows 10 x64 上使用动态编译的 QT 5.6.1(x86 和 x64)。问题:
我制作了一个基本程序编译了两次(x86 和 x64),它只显示一个带有按钮的窗口并将按钮连接到“点击”信号。我的窗口正确显示,但是当我按下按钮触发信号时,应用程序在退出连接到 SIGNAL 的 SLOT 后立即崩溃(从插槽正确调用 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时,结果是一样的。
【问题讨论】:
标头中的插槽名称与源中的不匹配。qapp(i, NULL);
- 这是错误的。您应该从main
传递参数
“它没有改变任何东西,但感谢这个建议”哦,它改变了一切,因为QCoreApplication
试图从参数中提取应用程序名称。在没有 argv
指向至少一个有效 C 字符串的情况下调用该构造函数是未定义的行为。你不应该实现_tmain
,Qt 已经为你做了。将您的代码放入常规的main
。
在您已经遇到的任何问题之上叠加甚至 更多 未定义的行为并没有帮助自己......“我已经改变了”不,你没有.确保您的问题与您的代码匹配,最好将 .ui
添加到问题中 - 但首先将其最小化,删除 .ui 文件中不会改变行为的任何内容!哎呀,也许您甚至不需要 .ui 并且可以在几行中以编程方式创建小部件。最小化!
你应该采取的方法与***无关。最小化是寻找错误的基本技术。
【参考方案1】:
感谢大家的帮助,终于找到问题了。
这是答案:
我的程序使用 stdcall (/Gz) 约定,但 QT 使用 cdecl (/Gd)。生成的 moc 文件是使用 stdcall 约定编译的,这就是导致问题的原因(由于被调用者和调用者之间的约定不同,释放参数时出现堆栈问题)。 现在我的程序是使用 stdcall 约定编译的(因为它对我来说是强制性的)但是生成的 moc 文件是用 cdecl 编译的,我已经在我的私人插槽标题上设置了 __cdecl 关键字!现在完美运行!
再次感谢您的宝贵时间。我希望这个主题有一天能帮助遇到类似问题的人。
【讨论】:
【参考方案2】:在隐藏小部件的子级上设置窗口模式是没有意义的。也许这是个问题。尝试以下操作,并检查它是否/何时崩溃。至少在 OS X 上肯定有一个 Qt 5.6 的 bug:当按钮的模态被还原时,小部件仍然没有接收到输入,你必须通过其他方式退出应用程序。
#include <QtWidgets>
int main(int argc, char **argv)
int n = 0;
QApplication appargc, 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();
【讨论】:
以上是关于QT 5.6.1 应用程序在退出插槽后仅在 x86 架构而不是 x64 上崩溃的主要内容,如果未能解决你的问题,请参考以下文章
每次构建后仅在活动选项卡中出现 Flash Builder 错误