shared_ptr<QCoreApplication> 崩溃

Posted

技术标签:

【中文标题】shared_ptr<QCoreApplication> 崩溃【英文标题】:shared_ptr<QCoreApplication> crashes 【发布时间】:2017-07-29 20:26:43 【问题描述】:

这个简单的代码在程序结束时崩溃(Qt 5.9.1,gcc 5.4.1):

#include <QCoreApplication>
#include <memory>

std::shared_ptr<QCoreApplication> manager;
int main(int argc, char *argv[])

    manager = std::make_shared<QCoreApplication>(argc, argv);

我知道通常的方法是在堆栈上声明一个QCoreApplication 实例,并在main() 的末尾将其销毁,但我的用例如下:我正在包装一个使用的库Qt 与 Boost.Python,当 python 模块被加载时,我像上面一样初始化 Qt。但是,我无法销毁QCoreApplication,除非我强制用户调用一些finalize() 方法。

当时的想法是在库(python 模块)被卸载时将其销毁,但这似乎不起作用。以上是预期的,如果是,为什么? “破坏顺序问题”是我的第一个猜测,但在这种情况下,这是否应该被视为一个错误?

【问题讨论】:

应用程序对象是一个全局变量/单例(您可以使用qAppQCoreApplication::instance() 获取它)并且初始化可能会做很多事情,我不确定您是否真的卸载它。最好从 Python 创建应用实例,然后直接使用它。 【参考方案1】:

问题(正如 Lukas 在上面的评论中指出的那样)是共享指针是一个全局对象,这意味着在进程退出时,直到 main() 返回之后才会调用它的析构函数,此时(我在推测,但非常有信心) QCoreApplication 对象的析构函数可能访问的各种数据结构已经被拆除和处置,因此当它尝试访问它们时会发生崩溃。 (例如,您传递给 QCoreApplication 构造函数的 argv 指针在 QCoreApplication 析构函数运行时可能不再有效)

但是,除非我强制,否则我无法销毁 QCoreApplication 用户调用一些 finalize() 方法。

您可以尝试的一件事是使用atexit() 注册一个回调函数,以删除 QCoreApplication 对象。希望 atexit() 回调将在关闭序列中尽早被调用,这将使您获得所需的行为。 (或者如果所有其他方法都失败了,您可以让 QCoreApplication 对象泄漏;因为无论如何该进程即将被销毁,我认为这样做不会特别有害)

【讨论】:

解释得很清楚,谢谢。从您链接的页面中:[...] 可用于 [...] 建立在卸载共享库时调用的函数。 虽然这似乎适用于我的基本示例问题,它不适用于 python 绑定的完整案例。我读到 here 应该定义调用顺序,但我认为(从 C++11 开始)this 适用:这些函数可以在销毁具有静态存储持续时间的对象的同时被调用。 . 经过更多测试,我找不到比泄漏QCoreApplication 对象更好的解决方案。接受答案,因为它提供了一个非常合理的解释。

以上是关于shared_ptr<QCoreApplication> 崩溃的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法将 shared_ptr<void> 转换为 shared_ptr<T>?

shared_ptr<QCoreApplication> 崩溃

使用相同的函数但重载不同的 std::tr1::shared_ptr<T> 和 std::shared_ptr<T>

vs2008关于C++的shared_ptr

shared_ptr 的循环依赖问题

为啥 shared_ptr 不允许直接分配