1

私の 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);
        }
    }
}

以前は、ロードされたプラグインを自分で破棄する必要があると考えていたので、plugins_(ポインターの QList)を反復処理して~MainForm()、それらを順番に削除しました。QPluginLoader後で、ドキュメントから、それを行うべきではないことがわかりました。その上、それはまた、プログラムを閉じたときにフリーズするという奇妙なバグを引き起こしました (ただし、デバッガーの下で実行した後のみ)。

から削除セクションを削除しまし~MainForm()たが、プラグインのデストラクタが呼び出されていないことに気付いたことを除いて、すべてが正常に機能しているようです。アプリケーションの終了時にいくつかのプラグイン固有の設定を保存するためにそれらに依存していましたが、そうでなければ気付かなかったでしょう。デストラクタの 1 つにブレークポイントを設定しましたが、デバッガはブレークポイントに入りませんでした。

プラグインの概要は次のとおりです。

// 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_;
}

私の質問は、プラグインはどのように破棄されるのですか? 私のプログラムが終了した後にOSがメモリを再利用するとき、明らかにそうでなければなりません。デストラクタが省略されているのはなぜですか?それらを解放することになっている他の方法はありますか?おそらく、元のQPluginLoaderオブジェクトをMainFormクラスでunload()有効にしてから、デストラクタで手動でそれらを保持しますか? QDialogデストラクタは、プラグインが所有する一部の および UI ウィジェットの破棄も担当していました。これは、プログラムの終了時にリークがあるということですか?

ありがとう!

更新:QPluginLoader各プラグインの sへのポインターを保存しようとしました。私は~MainForm()それらを繰り返し、それらを呼び出しunload()deleteing します。フリーズバグが戻ってきたことを除いて、正常に動作します。アプリケーションを閉じると、ウィンドウは消えますが、プログラムはデバッガーで実行され続けます。一時停止することはできますが、スタックには ntdll.dll に未確認のエントリ ポイントがいくつか表示されます。すぐに悪いことは起こらないようで、普通に走っていても目立たないのですが、なんとなく不安です。

更新 2:プログラムをフリーズ状態 (停止するのを忘れた) で実行したままにし、しばらくすると正常に終了したことがわかりました。20秒以上かかりました。今、私は本当に驚いています。何が原因でしょうか?

4

1 に答える 1