« krmovie.dll のビルド手順 | メイン | WMVソースフィルタ のメモリリーク »

2007年05月11日

吉里吉里 ムービー拡張日誌2:: 循環参照でメモリリーク

    

自動読み進みでひたすら回していると、メモリ不足に陥り、メモリ確保に失敗して落ちる問題が発覚。
メモリ使用量が増えていくのは画像キャッシュかと思っていたけど、メモリが枯渇するほどキャッシュするとは思えない。
メモリリークしているのだろうか?
画像キャッシュをOFFにして見ても使用量は増えている。
動作と使用量を見ていると、ムービーを再生するごとに増えていっている。
VideoOverlay の delete 時に開放出来ていないような。
使用しているのはWMV + レイヤー描画モード。

_CrtDumpMemoryLeaks を使えば、デバッグ出力に何度目に new されたメモリがリークしているかが表示される。
V2Unlink の最後に _CrtDumpMemoryLeaks を仕掛け、デバッグ出力で何度目に new されたものかを確認。
結構いっぱい出てる。
一番若い番号を _CrtSetBreakAlloc に指定して、もう一度動かす。
ブレークがかかった後は、呼び出し履歴(コールスタック)を見て、new 元を探る。
見てみると BufferRender だった。

だけど、BufferRender は CComPtr で自動的に Release されるはず。
また、BufferRender をフィルタグラフに追加した後は、フィルタグラフが Release するはず。
何かおかしい。
BufferRender の生成周りやフィルタグラフ構築周りでの、参照カウンタの増減を見ても特に不自然なところはない。
開放部分を追うがおかしなところは見当たらない。

さっぱりわからない。
ただ、IGraphBuilder の参照カウンタが1残っている。
どこかで開放し忘れているのだろうか?
確か、以前フィルタグラフが完全に停止しておらず、開放できないということがあった気がする。
今回もそうかと思い、追って見るも違う様子。
IGraphBuilder を2回 Release してみると、BufferRender のデストラクタが呼ばれ開放されていくが、当然落ちる。
どこかで開放できていないのは間違いないが、どこかわからない。

そこで、すべてのインターフェイスの開放時の参照カウンタ減少具合を見てみることにした。
すると IMediaSeeking や IMediaControl を Release するごとに参照カウンタが減っていっているように見える。
そして、最後に参照カウンタが1残る。
もしかして、これらの参照カウンタは共通なのか?
これらのインターフェイスは、IGraphBuilder に QueryInterface して取得しているが。

だとしたらあそこか!
以前、セグメントループのタイミングをより正確にする対応で、BufferRender 内でフィルタグラフからIMediaSeeking を取得し、IMediaSeeking から現在時間を取得するようにした。
そしてこの IMediaSeeking は、BufferRender のデストラクタで Release するようにした。
つまり、IGraphBuilder と BufferRender で循環参照が発生していたわけだ。
厳密には、IGraphBuilder と IMediaSeeking が参照カウンタを共有しており、BufferRender が IMediaSeeking を保持していたわけだ。
って言うか、そんなの知らないよ。

まあ、とにかく BufferRender で IMediaSeeking をデストラクタがコールされるまで持つのではなく、一時的に QueryInterface で取得してすぐに Release するようにすることで、このメモリリークは解消された。
ただ、レイヤー描画以外にもメモリリークは存在していた。

WMV のメモリリークに続く。



投稿者 Takenori : 2007年05月11日 22:57




comments powered by Disqus
Total : Today : Yesterday : なかのひと