为什么我的动态加载的Qt插件类没有调用析构函数?
Why isn't the destructor called for my dynamically-loaded Qt plugin class?
在我的C++Qt应用程序(字典查找/测验程序(中,我使用插件为某人可能想要添加和使用的所有可能的语言提供功能。这些插件在运行时从主小部件的构造函数中搜索和加载:
void MainForm::loadPlugins()
{
QDir curDir;
QStringList pluginFilter;
pluginFilter << "*_plugin.dll";
QStringList pluginFiles = curDir.entryList(pluginFilter, QDir::Files);
for (int i = 0; i < pluginFiles.size(); ++i)
{
const QString &pluginFile = pluginFiles.at(i);
QPluginLoader loader(pluginFile);
DictionaryPlugin *plug = qobject_cast<DictionaryPlugin*>(loader.instance());
if (plug)
{
plugins_.append(plug);
}
}
}
我曾经认为我应该自己销毁加载的插件,所以我在~MainForm()
中迭代了plugins_
(指针的QList(,按顺序删除它们。后来我从QPluginLoader
文档中发现我不应该这样做。此外,它还导致了一个奇怪的错误,导致程序在关闭时冻结(但仅在调试器下运行后(,因此它显然存在问题。
我从~MainForm()
中删除了删除部分,一切似乎都很好,除了我注意到插件的析构函数没有被调用。我依靠这些在应用程序终止时保存一些特定于插件的设置,否则我不会注意到。我在其中一个析构函数上放置了一个断点,调试器从未进入它。
以下是插件的概述:
// dict_plugin.h
class DictionaryPlugin
{
public:
virtual ~DictionaryPlugin() {}
virtual QString name() const = 0;
virtual QString language() const = 0;
/* ... */
};
Q_DECLARE_INTERFACE(DictionaryPlugin, "DictionaryPlugin")
// jp_plugin.h
class JpPlugin : public QObject, public DictionaryPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "JpPlugin")
Q_INTERFACES(DictionaryPlugin)
public:
JpPlugin();
virtual ~JpPlugin();
virtual QString name() const { return QString("Japanese plugin v1.0"); }
virtual QString language() const { return QString("Japanese"); }
/* ... */
};
// jp_plugin.cpp
JpPlugin::~JpPlugin()
{
saveSettings();
delete dictWidget_;
delete settWidget_;
delete kanjiDialog_;
delete wordDialog_;
delete radicalDialog_;
}
我的问题是,插件是如何销毁的?显然,当操作系统在我的程序终止后回收内存时,它们必须是。为什么省略了析构函数?我应该有其他方法释放他们吗?也许在 MainForm
类中保持原始QPluginLoader
对象处于活动状态,然后在析构函数中手动unload()
它们?析构函数还负责销毁插件拥有的一些QDialog
和 UI 小部件。这是否意味着程序退出时我有泄漏?
谢谢!
更新:我尝试为每个插件存储指向QPluginLoader
的指针。在~MainForm()
中,我迭代它们,调用unload()
并delete
它们。工作正常,除了冻结错误又回来了。当我关闭应用程序时,窗口消失,但程序继续在调试器中运行。我可以暂停它,但堆栈只显示 ntdll.dll 中的一些未识别的入口点。似乎没有什么立即发生的坏事,在正常运行时甚至看不到,但不知何故让我感到不安。
UPDATE2:我让程序在冻结状态下运行(忘记停止它(,发现它在一段时间后正常终止;它只花了大约 20+ 秒。现在我非常惊讶。什么原因可能导致这种情况?
我在谷歌上找到了这个:
QPluginLoader 有自己的引用计数,并在以下情况下删除插件 unload(( 已被为每个 QPluginLoader 实例调用 有一个把柄。unload(( 不会在 QPluginLoader 析构函数,因此插件永远不会自动删除。
它可以追溯到 2010 年,但也许您应该尝试保留对加载器的引用,并在程序结束时手动调用卸载。
这是文章的链接:
如何在Qt中卸载模块
- 什么时候调用析构函数
- C++-明确何时以及如何调用析构函数
- C++ 防止在映射中放置()时调用析构函数
- 调用析构函数以释放动态分配的内存
- C++:使用方法调用析构函数的顺序是什么?
- 向量推回调用析构函数时调用析构函数
- 如何在调用析构函数时优雅地停止/销毁带有阻塞调用C++线程?
- C++,我应该调用析构函数吗?
- 如何获取有关在 Clang LibTooling 中调用析构函数的信息?
- 当我从 std::vector 中的新放置调用析构函数时会发生什么?
- 为什么这里不调用析构函数
- 在调用 std::bind 的产品后意外调用析构函数
- 为什么在传递给函数而不是构造函数时调用析构函数?
- 如何在C++中调用析构函数
- 为什么为未删除的对象调用析构函数?
- 调用析构函数时出错
- C++ 在不释放内存的情况下调用析构函数
- 为什么在运算符删除中不调用析构函数?
- C++ 调用析构函数后动态模板队列"double free or corruption (out)"
- 在 postOrderDelete 上调用析构函数时引发的异常