アロケータ置換

仮想メモリ2GBの壁が問題になった。環境上 /3GB も使えない。冷やし中華さんはこう考えた。
「2GB以上のメモリは確保できない。ならメモリの確保はすべてメモリマップトファイルにしてしまえ」
試行段階としてvc9test20071228.cpp.txtを書いてみた。このコードはHeapAllocをCreateFileMapping & MapViewOfFileExの組み合わせ、要するにヒープ確保をメモリマップトファイル作成に置き換える。

static
LPVOID WINAPI NewHeapAlloc(
    __in HANDLE hHeap,
    __in DWORD dwFlags,
    __in SIZE_T dwBytes
    )
{
  void* result = NULL;
  LARGE_INTEGER l = { dwBytes };

  TCHAR tmpname[MAX_PATH];
  if (!::GetTempFileName(_T("."), _T("mm_"), 0, tmpname)) goto FAIL;
  HANDLE hFile = ::CreateFile(tmpname, GENERIC_READ | GENERIC_WRITE, 0, NULL, 
                              OPEN_ALWAYS, FILE_ATTRIBUTE_TEMPORARY, NULL);
  if (hFile == INVALID_HANDLE_VALUE) goto FAIL;

  HANDLE hMap = ::CreateFileMapping(hFile, NULL, PAGE_READWRITE, l.HighPart, l.LowPart, NULL);
  result = ::MapViewOfFileEx(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0, NULL);
  return result;

FAIL:
  ::SetLastError(STATUS_NO_MEMORY);
  return NULL;
//  return OldHeapAlloc(hHeap, dwFlags, dwBytes);
}

結論としてこの目論見は失敗なのだが、メモリマップトファイルは毎回ユニークなファイル名でCreateFileされるなど、結構面白いことができるものだと思った。

もっとも、ハンドルを開放しないことや、HeapFreeをUnmapViewOfFileに置換していないことなど、見て判るバグがあり、このままの実装の場合、致命的なバグとしてNewHeapAllocの実装の中でスタックオーバーフローが発生する。
GetTempFileNameおよびCreateFileは内部でRtlInitUnicodeStringExを呼ぶ。RtlInitUnicodeStringExは内部でRtlAllocateHeapを呼ぶらしく、結果再帰する。