ほとんどのユーザーがここで言ったように、あなたが扱っているメモリを発見する標準的な方法はありません。
また、多くのユーザーが指摘しているように、ヒープに割り当てられている場合は自動的に削除する関数へのポインターを渡すという、ちょっと変わった状況です。
しかし、あなたが主張するならば、それにもかかわらず、どのメモリがどのタイプに属するかを発見するいくつかの方法があります。
あなたは実際に3種類のメモリを扱っています
例えば:
char* p = new char[10]; // p is a pointer, points to heap-allocated memory
char* p = "Hello, world!"; // p is a pointer, points to the global memory
char p[] = "Hello, world!"; // p is a buffer allocated on the stack and initialized with the string
それでは、それらを区別しましょう。これをWindowsAPIとx86アセンブラーの観点から説明します(これは私が知っていることなので:))
スタックメモリから始めましょう。
bool IsStackPtr(PVOID pPtr)
{
// Get the stack pointer
PBYTE pEsp;
_asm {
mov pEsp, esp
};
// Query the accessible stack region
MEMORY_BASIC_INFORMATION mbi;
VERIFY(VirtualQuery(pEsp, &mbi, sizeof(mbi)));
// the accessible stack memory starts at mbi.BaseAddress and lasts for mbi.RegionSize
return (pPtr >= mbi.BaseAddress) && (pPtr < PBYTE(mbi.BaseAddress) + mbi.RegionSize);
}
ポインタが別のスレッドのスタックに割り当てられている場合は、レジスタ値GetThreadContext
を取得するだけでなく、スタックポインタを取得する必要があります。EIP
グローバルメモリ
bool IsGlobalPtr(PVOID pPtr)
{
MEMORY_BASIC_INFORMATION mbi;
VERIFY(VirtualQuery(pPtr, &mbi, sizeof(mbi)));
// Global memory allocated (mapped) at once for the whole executable
return mbi.AllocationBase == GetModuleHandle(NULL);
}
DLLを作成する場合は、の代わりにモジュールハンドル(実際にはベースマッピングポインタ)を配置する必要がありますGetModuleHandle(NULL)
。
ヒープ
理論的には、メモリがグローバルでもスタックでもない場合、ヒープに割り当てられていると想定できます。
しかし、実際にはここには大きなあいまいさがあります。
HeapAlloc
ヒープにはさまざまな実装があることを知っておく必要があります( /によってアクセスされる未加工のWindowsヒープHeapFree
、またはCRTでラップされたmalloc
/free
またはnew
/などdelete
)。
delete
このようなブロックは、スタック/グローバルポインタであるか、またはを介して割り当てられたことが確実にわかっている場合にのみ、演算子を介して削除できますnew
。
結論は:
- それはちょっと変質的なトリックです。一般的には使用しないでください。それを解放する方法を指示するポインターでいくつかの追加情報を提供することをお勧めします。
- どのヒープにメモリが割り当てられているかが確実にわかっている場合にのみ使用できます(ヒープメモリの場合)。