5

このバグ レポートでは、2007 年 6 月の時点で、Python インタープリターは、Python インタープリターが埋め込まれた C/C++ アプリケーションで Py_Finalize を呼び出した後、割り当てられたすべてのメモリをクリーンアップしないと述べています。アプリケーションの終了時に一度 Py_Finalize を呼び出すことが推奨されていました。

このバグ レポートは、バージョン 3.3 および 2011 年 3 月の時点で、インタープリターがまだメモリ リークを起こしていると述べています。

この問題の現在の状態を知っている人はいますか? 実行中のインスタンスごとにインタープリターが複数回呼び出されるアプリケーションがあり、メモリ リークが発生しているため、心配しています。

私は既に参照カウントを処理するために boost::python を使用しており、実行の間に Python プログラムを実行することによって作成されたすべての参照のグローバル ディクショナリをクリアします。私はいくつかのシングルトン クラスを持っています - これらは問題でしょうか?

これは扱いやすい問題ですか、それとも Python インタープリターのバグですか?

4

1 に答える 1

6

バグ (最初のもの、2007 年から) は nnorwitz によって「wontfix」としてクローズされており、彼の投稿はバグ レポートに含まれていることがわかります。

なんで何Py_Initialize/Py_Finalize度も電話するの?このようなことをしてみませんか (便宜上、C と Python を混ぜています):

/* startup */
Py_Initialize();

/* do whatever */
while (moreFiles()) {
    PyRun_SimpleString("execfile('%s')" % nextFile());
    /* do whatever */
}

/* shutdown */
Py_Finalize();

問題は、Python モジュールを作成するほとんどの人が、モジュールがファイナライズされて再初期化された場合に何が起こるかを気にせず、多くの場合、ファイナライズ中のクリーンアップを気にしないことです。モジュールの作成者は、プロセスが終了するとすべてのメモリが解放されることを知っており、それ以上のことは気にしません。

つまり、これは実際には 1 つのバグではなく、拡張モジュールごとに 1 つずつ、実に 1000 のバグです。少数のユーザーに影響を与えるバグの場合、これは膨大な量の作業であり、そのほとんどには実行可能な回避策があります。

への呼び出しはいつでも省略できます。2 回目のPy_Finalize呼び出しPy_Initializeは何もしません。これは、Python スクリプトを最初に実行するときにアプリケーションが追加のメモリを使用することを意味し、その追加のメモリは終了するまで OS に返されません。Python スクリプトを時々実行している限り、それをリークとは分類しません。あなたのアプリケーションは Valgrind クリーンではないかもしれませんが、ふるいのようにリークするよりはましです。

メモリ リークを避けるために (純粋な) Python モジュールをアンロードする必要がある場合は、それを行うことができます。から削除するだけsys.modulesです。

の欠点Py_Finalize: Python スクリプトを繰り返し実行している場合、それらの間で実行することはあまり意味がありませんPy_Finalize。再初期化するたびに、すべてのモジュールをリロードする必要があります。私のPythonは起動時に28個のモジュールをロードします。

追加の解説:バグは Python に限定されません。ライブラリをアンロードして再ロードしようとすると、どの言語でもかなりの量のライブラリ コードでメモリ リークが発生します。多くのライブラリが C コードを呼び出します。多くの C プログラマは、ライブラリが一度ロードされ、プロセスが終了するとアンロードされると想定しています。

于 2012-01-10T05:44:53.590 に答える