2016-04-07 7 views
1

SWIGを使用してC++で書かれたPythonのライブラリをラップしようとしています。ライブラリは、バイトバッファをパラメータとして受け入れる関数呼び出しを使用します。 Pythonでは、私はSWIGから%array_classを使ってこれらのバイトバッファを作成しています。私はこれをテストするために概念実証プログラムを作ったので、これらのバッファをC++に渡すことに伴う大きなメモリリークに気付きました。具体的には、以下のコードを実行すると、Pythonアプリケーション(タスクマネージャで確認)のメモリ使用量が着実に増加し、プログラムが停止する場所は約250MBになります。 Cからの出力は、プログラムが期待通りにを実行するが、より多くのメモリを消費することを示しています。 del buffステートメントは実行されますが、メモリを解放するものはありません。私は各ループでバッファを作成して削除しようとしましたが、同じ結果になりました。 C++でdelete x;を実行すると、プログラムが完全にクラッシュします。SWIGで生成されたオブジェクトのメモリ管理がCに渡されました

マイガブガブ飲むインタフェースファイル:

%module example 
%include "carrays.i" 
%array_class(uint8_t, buffer); 
%{ 
    #include "PythonConnector.h" 
%} 
%include "PythonConnector.h" 

Cヘッダファイル:

class PythonConnector { 
    public: 
     void print_array(uint8_t *x); 
}; 

最小のC定義関数

void PythonConnector::print_array(uint8_t *x) 
{ 
    //int i; 
    //for (i = 0; i < 100; i++) { 
    // printf("[%d] = %d\n", i, x[i]); 
    //} 
    //delete x;  // <-- This crashed the program 
    return; 
} 

テスターPythonスクリプト

import time 
import example 

sizeBytes = 10000 
buff = example.buffer(sizeBytes) 
for j in range(1000): 
    # Initialize data buffer 
    for i in range(sizeBytes): 
     buff[i] = i%256 
    buff[0] = 0 
    example.PythonConnector().print_array(buff.cast()) 
    print(j) 
del buff 
time.sleep(10) 

何か不足していますか?私は、SWIGが、バッファがガベージコレクションされていないC++に渡されるたびに、いくつかのプロキシオブジェクトを作成すると考えています。

編集:

  • SWIGバージョン3.0.7
  • CPythonのバージョン3.5のx64
  • のWindows 10 OS

ご協力いただきありがとうございます。

+0

私は、推測しなければならなかった場合、 'example.PythonConnector()'の繰り返し呼び出しから漏れてくると思います。あなたは本当にうまく問題を提起しました。試してみるのに必要なものはほとんどありません。あなたの例にクラス定義を追加することはできますか?私はそれが 'class PythonConnector {public:void print_array(unit8_t *); };しかし、私(または他の人たち)がこれをさらに調査する前に確認することは良いでしょう。 (SWIGとPythonのどちらのバージョンを使用していますか?) – Flexo

+0

@Flexo私はあなたが提案した追加を行いました。また、Pythonコネクターのインスタンス化をループ外に移し(唯一インスタンス化)、魅力的に働きました。メモリは常に6MBのままです。ありがとう。 –

+0

うまくいけば、私は今週末にそれがなぜ起こるのかを説明してくれることを願っています – Flexo

答えて

0

OK、@Flexoのおかげで、私は答えを見つけました。

問題は、各ループでexample.PythonConnector()をインスタンス化することです。

import time 
import example 

sizeBytes = 10000 
buff = example.buffer(sizeBytes) 
conn = example.PythonConnector() 
for j in range(1000): 
    # Initialize data buffer 
    for i in range(sizeBytes): 
     buff[i] = i%256 
    buff[0] = 0 
    conn.print_array(buff.cast()) 
    print(j) 
del buff 
time.sleep(10) 

は、まだ多くのコネクタが元のコードにガベージコレクションを取得しない理由を疑問が残る:ループの外に一度だけインスタンス化すると、メモリの問題を解決するようです。

関連する問題