IMallocSpy
COM公式ドキュメント
アプリケーション開発者が IMalloc メソッドの呼び出しにおけるメモリ割り当てを監視(スパイ)し、メモリリークを検出し、メモリ障害をシミュレートできるようにします。
メソッド 12
vtbl = vtable インデックス(0始まり)。HSP等からCOMメソッドをインデックス指定で呼ぶ際に使用します。0〜2 は IUnknown。
IMalloc::Alloc を呼び出す前に必要な処理を実行します。
| cbRequest | UINT_PTR | in | 呼び出し元が Alloc に渡す割り当て要求で指定されたバイト数。 |
戻り値
Alloc の呼び出しで指定されるバイト数。この値は cbRequest の値以上になることがあります。
解説(Remarks)
PreAlloc の実装では、デバッグ固有の情報を割り当てとともに格納するために、割り当てを拡張したり変更したりできます。
PreAlloc は 0 を返すことでメモリ割り当てを強制的に失敗させることができ、これによりアプリケーションがあらゆる場合に割り当て失敗を適切に処理できることをテストで確認できます。この場合、IMallocSpy::PostAlloc は呼び出されず、Alloc は NULL を返します。強制的な割り当て失敗は、cbRequest が 0 でない場合にのみ有効です。PreAlloc が NULL を返して失敗を強制している場合、PostAlloc は呼び出されません。ただし、Alloc が実際のメモリ障害に遭遇して NULL を返した場合は、PostAlloc が呼び出されます。
PreAlloc の呼び出しから PostAlloc の戻りまでは、スレッドセーフであることが保証されています。
IMalloc::Alloc を呼び出した後に必要な処理を実行します。
| pActual | void* | in | Alloc から返されたポインター。 |
戻り値
このメソッドは、実際に割り当てられたメモリブロックの先頭へのポインターを返します。このポインターは Alloc の呼び出し元にも返されます。デバッグ情報が呼び出し元の割り当ての先頭に書き込まれる場合、これは pActual から前方にオフセットしたポインターになります。デバッグ情報が末尾に付加される場合、またはデバッグ情報が付加されない場合は、この値は pActual と同じになります。
解説(Remarks)
IMallocSpy を実装したスパイオブジェクトが CoRegisterMallocSpy 関数を使用して登録されると、COM は Alloc の任意の呼び出しの後に PostAlloc を呼び出します。このメソッドは Alloc の呼び出しによって行われた割り当てへのポインターを入力として受け取り、割り当て全体の先頭へのポインターを返します。IMallocSpy::PreAlloc がこのような方法でデバッグ情報を割り当てに付加するように実装されている場合、これはもう一方の値から前方にオフセットしたポインターを含むことがあります。そうでない場合は、同じポインターが返され、Alloc の呼び出し元への戻り値にもなります。
IMalloc::Free を呼び出す前に必要な処理を実行します。このメソッドは、Free に渡されるポインターが実際の割り当ての先頭を指すことを保証します。
| pRequest | void* | in | 呼び出し元が Free に渡すメモリブロックへのポインター。 |
| fSpyed | BOOL | in | 解放されるメモリブロックが、現在のスパイがアクティブな間に割り当てられたかどうかを示します。 |
戻り値
IMalloc::Free に渡される値。
解説(Remarks)
IMallocSpy::PreAlloc が IMalloc::Alloc(または IMalloc::Realloc)に渡された元の割り当て要求を変更した場合、PreFree は実際の割り当てへのポインターを提供する必要があり、COM はそれを IMalloc::Free に渡します。たとえば、PreAlloc/PostAlloc のペアがデバッグ情報を格納するためのヘッダーを呼び出し元の割り当ての先頭に付加した場合、割り当てられたブロック全体を解放できるように、PreFree はこのヘッダーの先頭へのポインターを返す必要があります。
IMalloc::Free を呼び出した後に必要な処理を実行します。
| fSpyed | BOOL | in | 解放されるメモリブロックが、現在のスパイがアクティブな間に割り当てられたかどうかを示します。 |
解説(Remarks)
IMallocSpy を実装したスパイオブジェクトが CoRegisterMallocSpy 関数を使用して登録されると、COM は IMalloc::Free の任意の呼び出しの直後にこのメソッドを呼び出します。このメソッドは完全性と一貫性のために含まれています。開発者がこのメソッドに重要な機能を実装することは想定されていません。
IMalloc::Realloc を呼び出す前に必要な処理を実行します。
| pRequest | void* | in | IMalloc::Realloc の呼び出しで指定されたメモリブロックへのポインター。 |
| cbRequest | UINT_PTR | in | IMalloc::Realloc の元の呼び出しで指定されたメモリブロックのバイト数。 |
| ppNewRequest | void** | out | 再割り当てされるメモリブロックへのポインターを受け取るポインター変数のアドレス。PreRealloc の実装が再割り当てを拡張または変更する場合、これは pRequest のポインターとは異なることがあります。このポインターは常に PreRealloc によって格納される必要があります。 |
| fSpyed | BOOL | in | メモリブロックが、このスパイがアクティブな間に割り当てられたかどうかを示します。 |
戻り値
IMalloc::Realloc に渡されるバイト数。
解説(Remarks)
PreRealloc の実装では、デバッグ固有の情報を割り当てとともに格納するために、割り当てを拡張したり変更したりできます。したがって、ppNewRequest パラメーターは、Realloc の元の呼び出しで指定された要求へのポインターである pRequest とは異なることがあります。
PreRealloc は 0 を返すことでメモリ割り当てを強制的に失敗させることができ、これによりアプリケーションがあらゆる場合に割り当て失敗を適切に処理できることをテストで確認できます。この場合、PostRealloc は呼び出されず、Realloc は NULL を返します。ただし、Realloc が実際のメモリ障害に遭遇して NULL を返した場合は、PostRealloc が呼び出されます。強制的な割り当て失敗は、cbRequest が 0 でない場合にのみ有効です。
IMalloc::Realloc を呼び出した後に必要な処理を実行します。
| pActual | void* | in | Realloc の呼び出しで指定されたポインター。 |
| fSpyed | BOOL | in | メモリブロックが、現在のスパイがアクティブな間に割り当てられたかどうかを示します。 |
戻り値
このメソッドは、実際に割り当てられたブロックの先頭へのポインターを返します。このポインターは IMalloc::Realloc の呼び出し元にも返されます。デバッグ情報が呼び出し元の割り当ての先頭に書き込まれる場合、これは pActual から前方にオフセットしたポインターになります。デバッグ情報が末尾に付加される場合、またはデバッグ情報が付加されない場合は、この値は pActual と同じになります。
解説(Remarks)
スパイがアクティブな間にメモリの再割り当てが成功した場合、再割り当てされたメモリを追跡する後続の IMallocSpy メソッドの呼び出しでは、たとえ以前は fSpyed が FALSE であったとしても fSpyed は TRUE になります。
IMalloc::GetSize を呼び出す前に必要な処理を実行します。
| pRequest | void* | in | 呼び出し元が GetSize に渡すポインター。 |
| fSpyed | BOOL | in | メモリブロックが、現在のスパイがアクティブな間に割り当てられたかどうかを示します。 |
戻り値
サイズを求める対象となる実際の割り当てへのポインター。
解説(Remarks)
PreGetSize メソッドは、呼び出し元が IMalloc::GetSize に渡すポインターを pRequest パラメーターとして受け取ります。次に、実際の割り当てへのポインターを返す必要があります。この pRequest は、IMallocSpy の PreAlloc メソッドまたは PreRealloc メソッドの実装において変更されている可能性があります。その後、実際の割り当てへのポインターが GetSize の pv パラメーターとして渡されます。
続いて IMalloc::GetSize が求めたサイズを返し、COM はこの値を cbActual として IMallocSpy::PostGetSize に渡します。
GetSize が求めるサイズは、HeapSize 関数が返す値です。これは元々要求されたサイズです。たとえば、27 バイトのメモリ割り当て要求は 32 バイトの割り当てを返しますが、GetSize は 27 を返します。
IMalloc::GetSize を呼び出した後に必要な処理を実行します。
| cbActual | UINT_PTR | in | GetSize が返した、割り当てのバイト数。 |
| fSpyed | BOOL | in | メモリブロックが、現在のスパイがアクティブな間に割り当てられたかどうかを示します。 |
戻り値
IMalloc::GetSize が返す値。これは割り当てられたメモリブロックのサイズ(バイト単位)です。
解説(Remarks)
GetSize が求めるサイズは、HeapSize 関数が返す値です。これは元々要求されたサイズです。たとえば、27 バイトのメモリ割り当て要求は 32 バイトの割り当てを返しますが、GetSize は 27 を返します。
IMalloc::DidAlloc を呼び出す前に必要な処理を実行します。
| pRequest | void* | in | DidAlloc の呼び出しで指定されたポインター。 |
| fSpyed | BOOL | in | 割り当てが、このスパイがアクティブな間に行われたかどうかを示します。 |
戻り値
fActual パラメーターとして DidAlloc に渡される値。
解説(Remarks)
IMallocSpy を実装したスパイオブジェクトが CoRegisterMallocSpy 関数で登録されると、COM は IMalloc::DidAlloc の任意の呼び出しの直前にこのメソッドを呼び出します。このメソッドは完全性と一貫性のために含まれています。開発者がこのメソッドに重要な機能を実装することは想定されていません。
IMalloc::DidAlloc を呼び出した後に必要な処理を実行します。
| pRequest | void* | in | DidAlloc の呼び出しで指定されたポインター。 |
| fSpyed | BOOL | in | 割り当てが、このスパイがアクティブな間に行われたかどうかを示します。 |
| fActual | INT | in | DidAlloc が返した値。 |
戻り値
DidAlloc の呼び出し元に返される値。
解説(Remarks)
IMallocSpy を実装したスパイオブジェクトが CoRegisterMallocSpy 関数を使用して登録されると、COM は DidAlloc の任意の呼び出しの直後にこのメソッドを呼び出します。このメソッドは完全性と一貫性のために含まれています。開発者がこのメソッドに重要な機能を実装することは想定されていません。
利便性のため、DidAlloc の呼び出しで渡された元のポインターである pRequest が PostDidAlloc に渡されます。さらに、パラメーター fActual は、この値が実際に DidAlloc に渡されたかどうかを示すブール値です。渡されなかった場合は、何らかのデバッグ目的でこのポインターを変更するように IMallocSpy::PreDidAlloc が実装されていたことを示します。
IMalloc::HeapMinimize を呼び出す前に必要な処理を実行します。
解説(Remarks)
このメソッドは完全性のために含まれています。開発者がこのメソッドに重要な機能を実装することは想定されていません。
IMalloc::HeapMinimize を呼び出した後に必要な処理を実行します。
解説(Remarks)
IMallocSpy を実装したスパイオブジェクトが CoRegisterMallocSpy 関数を使用して登録されると、COM は IMalloc::Free の任意の呼び出しの直後にこのメソッドを呼び出します。このメソッドは完全性と一貫性のために含まれています。開発者がこのメソッドに重要な機能を実装することは想定されていません。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)
HSP用 COM定義
#usecom / #comfunc によるHSPのCOM呼び出し定義。数字は vtbl インデックス(0始まり)。クラスIDが無い場合 #usecom の末尾は "{}"、ある場合は "{CLSID}"。
#define global IID_IMallocSpy "{0000001D-0000-0000-C000-000000000046}"
#usecom global IMallocSpy IID_IMallocSpy "{}"
#comfunc global IMallocSpy_PreAlloc 3 sptr
#comfunc global IMallocSpy_PostAlloc 4 sptr
#comfunc global IMallocSpy_PreFree 5 sptr,int
#comfunc global IMallocSpy_PostFree 6 int
#comfunc global IMallocSpy_PreRealloc 7 sptr,sptr,sptr,int
#comfunc global IMallocSpy_PostRealloc 8 sptr,int
#comfunc global IMallocSpy_PreGetSize 9 sptr,int
#comfunc global IMallocSpy_PostGetSize 10 sptr,int
#comfunc global IMallocSpy_PreDidAlloc 11 sptr,int
#comfunc global IMallocSpy_PostDidAlloc 12 sptr,int,int
#comfunc global IMallocSpy_PreHeapMinimize 13
#comfunc global IMallocSpy_PostHeapMinimize 14
; ※数字は vtbl インデックス(0始まり)。0/1/2 は IUnknown(QueryInterface/AddRef/Release)。
; ※このインターフェースは直接 CoCreateInstance するクラスIDが無いため "{}"(他メソッド/アクティベーションで取得)。
; ※ハンドル/void*等の不透明ポインタは IronHSP では intptr 指定が可能。