Windowsのメモリアロケーション関数の関係について整理した

C++/CLIで、new演算子で確保したアンマネージドメモリをMarshal::FreeHGlobal()で解放しようとするとエラーになってなぜだろうと思い調べた。

ソース抜粋

  • メモリ確保
unsigned char *test = new unsigned char[100];
  • 問題ないメモリ解放
//これは問題ない
delete [] test;
  • 例外が起きるメモリ解放
//こう書くと例外
System::Runtime::InteropServices::Marshal::FreeHGlobal(IntPtr(test));

MSDNのドキュメントとVisual Studioの逆アセンブリ機能で調べると以下が判明

f:id:n-noguchi:20181114212433p:plain

よく見ると、メモリ確保のメカニズムがことなるので正しい関数で解放しなきゃいけないと書いてある。 たぶん、今回の問題も同じようにメモリ確保と対になる正しい関数でメモリ解放しなさいということなんだろう。

Because the different heap allocators provide distinctive functionality by using different mechanisms, you must free memory with the correct function. For example, memory allocated with HeapAlloc must be freed with HeapFree and not LocalFree or GlobalFree. Memory allocated with GlobalAlloc or LocalAlloc must be queried, validated, and released with the corresponding global or local function.

引用元:Comparing Memory Allocation Methods

つまりこういうことなんだろう

メモリ確保関数 メモリ解放関数
HeapAlloc HeapFree
GlobalAlloc GlobalFree
LocalAlloc LocalFree
Marshal::AllocHGlobal Marshal::FreeHGlobal
new演算子 delete演算子
malloc free