Aspen Plus というシミュレーション ソフトウェアへの COM インターフェイスにアクセスする C# プログラムがあります。非常に奇妙なメモリリークがあります。
シミュレーションから結果値を取得する必要がある場合は、このような一連の呼び出しを実行します。場合によっては、返される変数が null になる可能性があるため、そのためのチェックを挿入します。次に、FinalReleaseComObject を使用して COM 参照をクリーンアップします。
public override ValueType recvValueFromSim<ValueType>(string path) {
Happ.IHNode tree = this.Aspen.Tree;
dynamic node = tree.FindNode(path);
ValueType retVal = default(ValueType);
if (node != null && node.Value != null) {
retVal = node.Value;
}
Marshal.FinalReleaseComObject(node);
Marshal.FinalReleaseComObject(tree);
node = null;
return retVal;
}
残念ながら、上記のコードには多くのリークがあります。シミュレーションごとに 2MB リークします。最初は、ガベージ コレクターが最終的に実行されてクリーンアップされると思っていましたが、ダイスはありませんでした。数百回のシミュレーションを実行した後、メモリが不足しました。
奇妙なことに、以下のコードは正常に動作し、リークしません。null 参照をチェックするために catch を使用するのは悪い形式のように思えるので、私はそれが好きではありませんでしたが、これはリークしません。
public override ValueType recvValueFromSim<ValueType>(string path) {
ValueType node;
try {
node = this.Aspen.Tree.FindNode(path).Value;
return node;
} catch {
return default(ValueType);
}
}
漏れないのはなぜ?誰か知っていますか?一時的な参照と COM オブジェクトの解放について知っていると思った理由は嘘です。