使用 ActiveX 服务器调用 QCoreApplication::arguments() 时崩溃
Invoking QCoreApplication::arguments() crashes using an ActiveX server
我们正在构建一个包含一些 QObject 和 QWidget 的库。这个想法是使用 ActiveX (QAxContainer) 提供 COM 对象,以便它们可以嵌入并与其他语言(在本例中为托管 C#)结合使用。
我们使用的一些对象将与 Qt Quick 集成,为此我们使用 QQuickWidget。在 QQuickWidget 构造期间,它将调用 QCoreApplication::arguments() ,这会导致访问冲突:
Exception thrown at 0x00007ffc43f12fc0 (ucrtbased.dll) in WinClient.exe: 0xC0000005: Access violation reading location 0xffffffffffffffff
将以下 class 导出到 ActiveX 小部件将导致崩溃:
#include <QWidget>
#include <ActiveQt/QAxBindable>
class TestAxWidget: public QWidget, public QAxBindable
{
Q_OBJECT
Q_CLASSINFO("ClassID", "{377794ac-85f2-4e2c-be17-f2852d85fa61}")
Q_CLASSINFO("InterfaceID", "{8b3a6ef3-9d17-47f7-99a8-cd96d0d922dd}")
Q_CLASSINFO("EventsID", "{12e9000e-017e-454e-a641-73c9p8349d77}")
Q_CLASSINFO("CoClassAlias", "TestAxWidget")
Q_CLASSINFO("RegisterObject", "yes")
public:
explicit TestAxWidget(QWidget * parent = Q_NULLPTR)
: QWidget(parent)
{
QCoreApplication::arguments();
}
Q_DISABLE_COPY(TestAxWidget)
};
和堆栈跟踪:
ucrtbased.dll!strlen() + 0x10 bytes
Qt5Cored.dll!QString::fromLocal8Bit(const char * str, int size) Line 539 + 0x19 bytes C++
Qt5Cored.dll!QCoreApplication::arguments() Line 2313 + 0x1e bytes C++
关于如何解决这个问题有什么建议吗?
更新
在使用 Qt 源进行进一步调试后,我发现提供给 QCoreApplication() 的 argc
被初始化为 0(零)。
当调用 QCoreApplication::arguments() 时,argc 的值已更改为某个随机高值 != 0,这显然会导致异常。
我在 VS2015 中使用了 Data Breakpoint
来识别 argc 的值何时更改并且它似乎定期被 clr.dll
更改。我怎样才能防止这种情况发生?我做错了什么吗?
目前在 Windows 10 x64 VS2015
上使用 Qt 5.6.2
我认为在不更改主应用程序(我认为是用 C# 编写)的情况下解决此问题的唯一方法是在您的库中创建 QApplication 实例,并 运行 QApplication::exec 用于发送 GUI 消息 from/to QWidgets 实例。
在 QAxServerBase.cpp 中通过函数 CreateInstanceHelper:
实例化 QApplication 时显然存在错误
...
if (!qApp) {
qax_ownQApp = true;
int argc = 0;
new QApplication(argc, 0);
}
...
应用程序崩溃,因为传入的参数 argc
是在堆栈上创建的,并且不会超过 QApplication 实例。
在 5.9.0 版本中有一个错误修复:
https://bugreports.qt.io/browse/QTBUG-59047
我们正在构建一个包含一些 QObject 和 QWidget 的库。这个想法是使用 ActiveX (QAxContainer) 提供 COM 对象,以便它们可以嵌入并与其他语言(在本例中为托管 C#)结合使用。
我们使用的一些对象将与 Qt Quick 集成,为此我们使用 QQuickWidget。在 QQuickWidget 构造期间,它将调用 QCoreApplication::arguments() ,这会导致访问冲突:
Exception thrown at 0x00007ffc43f12fc0 (ucrtbased.dll) in WinClient.exe: 0xC0000005: Access violation reading location 0xffffffffffffffff
将以下 class 导出到 ActiveX 小部件将导致崩溃:
#include <QWidget>
#include <ActiveQt/QAxBindable>
class TestAxWidget: public QWidget, public QAxBindable
{
Q_OBJECT
Q_CLASSINFO("ClassID", "{377794ac-85f2-4e2c-be17-f2852d85fa61}")
Q_CLASSINFO("InterfaceID", "{8b3a6ef3-9d17-47f7-99a8-cd96d0d922dd}")
Q_CLASSINFO("EventsID", "{12e9000e-017e-454e-a641-73c9p8349d77}")
Q_CLASSINFO("CoClassAlias", "TestAxWidget")
Q_CLASSINFO("RegisterObject", "yes")
public:
explicit TestAxWidget(QWidget * parent = Q_NULLPTR)
: QWidget(parent)
{
QCoreApplication::arguments();
}
Q_DISABLE_COPY(TestAxWidget)
};
和堆栈跟踪:
ucrtbased.dll!strlen() + 0x10 bytes
Qt5Cored.dll!QString::fromLocal8Bit(const char * str, int size) Line 539 + 0x19 bytes C++
Qt5Cored.dll!QCoreApplication::arguments() Line 2313 + 0x1e bytes C++
关于如何解决这个问题有什么建议吗?
更新
在使用 Qt 源进行进一步调试后,我发现提供给 QCoreApplication() 的 argc
被初始化为 0(零)。
当调用 QCoreApplication::arguments() 时,argc 的值已更改为某个随机高值 != 0,这显然会导致异常。
我在 VS2015 中使用了 Data Breakpoint
来识别 argc 的值何时更改并且它似乎定期被 clr.dll
更改。我怎样才能防止这种情况发生?我做错了什么吗?
目前在 Windows 10 x64 VS2015
上使用 Qt 5.6.2我认为在不更改主应用程序(我认为是用 C# 编写)的情况下解决此问题的唯一方法是在您的库中创建 QApplication 实例,并 运行 QApplication::exec 用于发送 GUI 消息 from/to QWidgets 实例。
在 QAxServerBase.cpp 中通过函数 CreateInstanceHelper:
...
if (!qApp) {
qax_ownQApp = true;
int argc = 0;
new QApplication(argc, 0);
}
...
应用程序崩溃,因为传入的参数 argc
是在堆栈上创建的,并且不会超过 QApplication 实例。
在 5.9.0 版本中有一个错误修复: https://bugreports.qt.io/browse/QTBUG-59047