使用 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