简体   繁体   English

为什么 Qt5 会出现奇怪的崩溃,这取决于我创建应用程序实例的方式?

[英]Why am I getting weird crashes with Qt5 depending on how I create the application instance?

Here is a reduced version of my code:这是我的代码的简化版本:

#include <QtWidgets/QApplication>
#include <QtWidgets/QMainWindow>


class MainView : public QMainWindow
{
    public:
        static MainView *Initialise(int argc, char **argv);

        int Run() { return qApp->exec(); }

    private:
        MainView() { }
        virtual ~MainView() { }

};


namespace
{
    QApplication *s_app      {nullptr};
    MainView     *s_instance {nullptr};
};


MainView *MainView::Initialise(int argc, char **argv)
{
    if (nullptr == s_app) {
        s_app = new QApplication(argc, argv);
    }

    if (nullptr == s_instance) {
        s_instance = dynamic_cast<MainView *>(new MainView());
    }

    return s_instance;
}


class Framework
{
    public:
        Framework() { }
        ~Framework() { }

        int Initialise(int argc, char **argv)
        {
            m_main_view = MainView::Initialise(argc, argv);

            return 0;
        }

        int Run()
        {
            m_main_view->show();
            return m_main_view->Run();
        }

    private:
        MainView *m_main_view;

};


int main(int argc, char **argv)
{
    Framework  framework;
    int        result = 0;

    // Weirdness here!!!!
    MainView::Initialise(argc, argv);  // Crashes even with this line.

    result = framework.Initialise(argc, argv);
    if (0 == result) {
        result = framework.Run();
    }

    return result;
}

This code crashes when showing the MainWindow instance.此代码在显示 MainWindow 实例时崩溃。 In my full version of this code, where MainView inherits from a virtual interface class (so as to allow me to decouple the view and substitute a command line interface or a test interface) it doesn't crash unless I comment out the code marked as "weirdness here".在此代码的完整版本中,MainView 从虚拟接口 class 继承(以便我解耦视图并替换命令行接口或测试接口)它不会崩溃,除非我注释掉标记为的代码“这里很奇怪”。

In this code, if I replace:在这段代码中,如果我替换:

MainView::Initialise(argc, argv);  // Crashes even with this line.

with:和:

if (nullptr == s_app) {
    s_app = new QApplication(argc, argv);
}

then it works fine and doesn't crash.然后它工作正常并且不会崩溃。

Essentially if the application is instantiated within MainView::Initialise() , whether called from main() or from Framework::Initialise() then the program crashes, but if I initialise the application in main() first then it doesn't crash.本质上,如果应用程序是在MainView::Initialise()中实例化的,无论是从main()还是从Framework::Initialise()调用,程序都会崩溃,但如果我先在main()中初始化应用程序,那么它不会崩溃.

I don't want my main() function to have any knowledge of the UI at all, if possible, even taking my virtual base class interface into account.如果可能的话,我不希望我的main() function 对 UI 有任何了解,即使考虑到我的虚拟基础 class 接口也是如此。 There should be no need and it makes main() messier than necessary.应该没有必要,它使main()比必要的更混乱。

So why is this crashing and how do I stop it?那么为什么会崩溃,我该如何阻止它呢?

There's a subtle difference between your invocation of the QApplication constructor in main() and the invocation in MainView::Initialise() .您在main()中调用QApplication构造函数与在MainView::Initialise()中调用之间存在细微差别。

The documentation for the QApplication constructor says: QApplication 构造函数的文档说:

QApplication:: QApplication ( int &argc, char **argv) QApplication:: QApplication ( int &argc, char **argv)

<... > <... >

Note: argc and argv might be changed as Qt removes command line arguments that it recognizes.注意: argc 和 argv 可能会更改,因为 Qt 删除了它识别的命令行 arguments。

So when invoking the constructor in MainView::Initialise() , you are actually passing a copy of the argc that came from main.因此,在MainView::Initialise()中调用构造函数时,实际上是在传递来自 main 的argc的副本。 Presumably, Qt stores a reference to this internally somewhere, causing it to crash when the QApplication later dereferences it during the construction of the window.据推测,Qt 在内部某处存储对此的引用,导致它在 QApplication 稍后在构建 window 期间取消引用时崩溃。

If you change the signature of both Initialise() functions to take a reference to argc, the program works without crashing.如果您更改两个Initialise()函数的签名以引用 argc,则程序可以正常工作而不会崩溃。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM