Chapter.14

IMallocSpy

2005/1/7
 ・インターフェースが継承可能であることが判明したのでサンプルソースを修正。

1.タスクアロケーター

VB.NETのようなメモリを直接扱わない言語を使用すると、メモリの確保・開放を特に意識しません。 しかし、.NET Frameworkのランタイムは、メモリの管理をプログラマの見えない所でひっそりと行っているはずです。 COMの機能を利用する場合、COMとのメモリのやり取りは、COMのメモリ管理機能であるタスクアロケーターを使用する必要があります。 この章では、.NET FrameworkのCOM相互運用機能を使用した場合に、タスクアロケーターが正常に使用されているかを見てみることにします。

左の図は、タスクアロケーターのメモリ割り当てを追跡する機能を持ったフォームです。 上段にメモリの割り当て状態を表示し、下段には実際にメモリの割り当てと開放のログが記録されます。 メニューには、ログ画面をクリアする機能を搭載してあります。

これを前回までに作成したアプリケーションに組み込んだサンプルソースです。
VB.NETサンプルソース:chap14.vb.lzh(39KB 2005/1/7)

サンプルを動作させてみると操作ごとにメモリの確保と開放が行われているのが分かると思います。 このうち特に分かりやすいのは、IOleObject.GetUserTypeです。 これは、オブジェクトの種類を表す文字列を取得するメソッドですが、OLEサーバ側から文字列を返却するのに、タスクアロケーターを使用しています。 一回の呼び出しにつき、一つ文字列が返されるので、三回呼び出しているこのサンプルでは、三回メモリの確保と開放が行われるはずです。 確認してみて下さい。

インプレースアクティベーションを行うと、多数のメモリ(多量ではない)が確保されることが分かります。 様々なサーバでテストしてみて下さい。


2.メモリ管理

メモリをトレースするのに使用するのは、IMallocSpyというインターフェースです。 このインターフェースをCoRegisterMallocSpy関数で、システムに登録するのですが、1プロセスにつき1つしか登録することは出来ません。 ActiveXの製品の中には、このインターフェースを実装し、メモリの管理を行ってくれるものが市販されています。 このフォームをそういった製品と併用すると競合が発生することになります。

前項で述べたとおり、COM相互運用機能が使用するメモリをトレースすることが可能となりました。 ただし、これはタスクアロケーターを使用するメモリだけで、OLEが頻繁に使用するグローバル/ローカルヒープメモリGlobalAlloc/LocalAlloc等で確保されるメモリ)をトレースすることは出来ません。 グローバル/ローカルヒープメモリを直接扱わなければならない場合、プログラマはマネッジドコードを離れて、自分でメモリを管理する必要が出てきます。 その場合、似たような独自のメモリ管理機能を実装することをお勧めします。


3.まとめ

サンプルを動作させると分かりますが、メモリの全てが完全に開放されることはありません。 これは、好意的に考えると.NET Frameworkが内部で使用しているメモリを開放する前に、プログラムが終了しているため、ログに残らないと考えることが出来ます。 しかし、私は、これを単純にメモリリークしていると考えています。 ただし、メモリリークしているのが、OLEサーバ側か、.NET Framework側かは不明ですが・・・。 少なくとも、VB.NETを使用している限り、メモリを直接制御することは出来ないため、どちらかが悪いと考えるしかありません。 現在の.NET Frameworkを使用して、OLE関連のプログラムを制作する場合、リークの可能性があることを前提として設計した方が良さそうです。

このサンプルは当初、System.Windows.Forms.ListViewを使用して、メモリの使用状況が一目でわかるように作成していました。 ところが、リストビューに項目を追加すると、IMallocSpy.PreAllocIMallocSpy.PostAllocが呼び出されるのです。 このため、相互再帰に陥ってしまい、リストビューでメモリを管理するのを諦めざるを得ませんでした。 System.Windows.Forms.ListViewクラスが、タスクアロケーターを使用していると考えられます。


前へ 次へ
OLE on .NET Frameworkへ
総合トップへ