2010年2月13日土曜日

OBConversionでメモリーリーク?

OpenBabelの構造コンバーターの「OBConversion」はめちゃくちゃたくさんの構造フォーマットに対応した便利なConverterなんですが、どうも変な動きをすることがあります。

たとば、下記のようにMolの配列にSmiles文字列の配列をConvertしながら入れる場合、下記のコードはVisualStudioでは特に問題ありません。

(コードA)
for(i=0; i < 3; i++)
{
    OBConversion conv = new OBConversion();
    conv.SetInAndOutFormats("smi", "can");
    conv.ReadString(obMol[i], obSmi[i]);
}

しかし下記のコードのように、CML文字列を変換する場合、実行中は何も問題ないのですが、終了するとメモリーエラーを起こします。

(コードB)

for(i=0; i < 3; i++)
{
    OBConversion conv = new OBConversion();
    conv.SetInAndOutFormats("cml", "can");
    conv.ReadString(obMol[i], obCml[i]);
}

これは正しくは、こうするべきです。

(コードC)
for(i=0; i < 3; i++)
{
    OBConversion conv = new OBConversion();
    conv.SetInAndOutFormats("cml", "can");
    conv.ReadString(obMol[i], obCml[i]);

    conv.Dispose();
    conv = null;
}

つまり、使用後のOBConversionインスタンスはちゃんと破棄する必要があります。このコードでは終了しても何もエラーがなく正常に動きます。

ただ不思議なのはコードAではメモリーエラーを起こさず、コードBではエラーを起こす点です。

想像するにCMLのConvertで何か内部的なメモリーの破棄忘れがあって、破棄しない場合にメモリーリークを起こしているではと思ってます。

さらにはコードCでもメモリーエラーを起こす場合があります。これはコードCを含む関数をdelegateで使う場合で、OBConversionのインスタンスが正常に破棄されず、ReadStringの箇所でメモリーエラーを起こします。

ということで、実用問題としてOpenBabelのCML変換は使えない、という結論に達しました。

これがわかるのに2日もかかりました。

ということでCML変換はCDKでやることにしました。その内容はまた別に書きます。

0 件のコメント: