【问题标题】:Do I need to delete point in plugin class in Qt?我需要删除 Qt 插件类中的点吗?
【发布时间】:2021-02-16 22:28:27
【问题描述】:

现在,我完善我的问题。指针 m_Core 将被初始化,并且肯定会首先调用 GetCore()。我最关心的是文档说当 QPluginLoader 完全卸载时会自动删除根组件,我不不知道当 Qt 破坏 QPluginloader 和实例时 Qt 如何处理内存。如果Qt会在QPluginLoader销毁之前删除Object,我就不需要手动释放了。事实上,当我将delete m_Core无效时,Qt 不会报错,如果我有效,Qt 会报段错误,所以Qt 必须在调用~Mplugin() 函数之前破坏Mplugin 类。

m_Core 是 QWidget 的派生类: SF_Core.h

#include <QWidget>
class SF_Core:public QWidget
{
    SF_Core(QWidget* parent):QWidget(parent){}
    ~SF_Core(){}
};

我通过 QPluginLoader 在我的项目中使用它,如下所示:

mainWindow.h
#include "MInterface.h"
#include "SF_Core.h"
#include <QWidget>
class MainWindow:public QWidget
{
   Q_Object
   MainWindow();
   ~MainWindow();
private:
   MInterface* interface;
   QObject* plugin;
   MCore* core;
}
mainWindow.cpp
void mainWindow::mainWindow()
{
   QPluginLoader loader("SF_Core.dll");
   plugin = loader.instance(); 
   interface = qobject_cast<MInterface* >(plugin);
   core = interface->GetCore();
}

我有一个从Qt程序中的MIngerface类派生的插件类,并重写了MIngerface中的函数GetCore()。

#include "SF_Core.h"
class Mplugin:public QObject,MInterface
{
    Q_OBJECT
    Q_PLUGIN_METADATA(IID INTERFACE_ID)
    Q_INTERFACES(MInterface)
public:
    Mplugin();
    ~Mplugin(){
      delete m_Core;
    }
    SF_Core* GetCore(){
    m_Core = new SF_Core;
    return m_Core;
    }    
private:
    SF_Core* m_Core;
};

在主程序中,我通过QPluginLoader加载插件,并使用instance()获取根组件。当我终止程序时,它崩溃了。我发现错误来自这句话delete m_Core;如果我不删除m_Core,会导致内存泄漏吗?

【问题讨论】:

  • 您确定至少调用了一次 GetCore 吗?也许它崩溃了,因为它从未被调用过,并且 m_Core 包含未初始化的垃圾(它不是智能指针,您没有在 ctor 中将其归零)。另一种可能性是调用 GetCore 并将“SF_Core”的所有权转移到某个 q 组件,该组件在应用程序关闭时为您销毁它,然后您的删除尝试第二次删除它。但你的情况是哪一种,扔硬币吧。
  • 我建议要么使用final,要么声明析构函数virtual

标签: c++ qt


【解决方案1】:

初步简短回答

牢记所有权原则,很可能是的:它会导致内存泄漏。

另外,考虑到对GetCore 的每次调用都会分配一个新实例并造成内存泄漏。

但是,如果没有完整的示例,很难理解SF_Core 是如何使用的,尤其是在所有权是否转让的情况下。


堆栈变量修复

如果您使用内部堆栈值怎么办? (不是最佳做法,但要发布内部属性)

SF_Core* GetCore()
{
    return &m_Core;
}    
private:
SF_Core m_Core;

使用 shared_ptr 的替代方法

另一种方法是使用智能指针(我强烈建议尽可能地使用原始指针):

using SfCorePtr = std::shared_ptr<SF_Core>;
SfCorePtr GetCore()
{
    if (!m_CorePtr)
    {
        m_CorePtr = std::make_shared<SF_Core>(); // Lazy creation
    }
    return m_CorePtr;
}    
private:
SfCorePtr m_Core;

提示:更迂腐的是,std::weak_ptr 的使用允许在不提供所有权的情况下访问智能指针:如果 GetCore 返回 weak_ptr,则 m_Core 的所有权保留在此对象中,并且所有权保持在树形而不是图形形。


最小修复

否则,只需修复您的代码:

#include "Mcore.h"
class Mplugin:public QObject,MInterface
{
    Q_OBJECT
    Q_PLUGIN_METADATA(IID INTERFACE_ID)
    Q_INTERFACES(MInterface)
public:
    Mplugin();
    virtual ~Mplugin(){
        delete m_Core;
    }
    SF_Core* GetCore(){
        if (nullptr == m_Core){
            m_Core = new SF_Core;
        }
        return m_Core;
    }    
private:
    SF_Core* m_Core=nullptr;
};

【讨论】:

  • 我快速搜索了一下,没有找到关于 SF_Core 的文档,Qt 通常在它的类前面加上 QQt;所以我希望这个类是从 OP 定制的。无论如何,我听从了您的建议,并针对不同的情况确定了答案。
  • 我更新了我的问题,我应该如何编写 Mplugin 类的析构函数?
  • 哦,我的意思是请你告诉我 QPluginLoader 被破坏后 Qt 会做什么,以及 Qt 何时释放由 instance() 函数创建的实例的内存。 instance() 的返回值是根组件的 QObject 指针,并分配给 mainwindow 中的一个私有成员,指针插件。据我了解,当插件指针被删除时,instance() 分配的内存被释放,所以我需要在我的 mainWindow 的析构函数中删除插件和 m_Core,对吗?非常感谢您的帮助!!!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多