// MemAlloc.cpp -- Implementations for the memory allocation routines used within Tome #include "StdAfx.h" static HANDLE hheap = NULL; static UINT cAllocs = 0; static UINT cbAllocated = 0; static UINT cFrees = 0; static UINT cbFreed = 0; // static SYSTEM_INFO si; static PVOID pvTrap= NULL; #define HEAP_SIZE_LIMIT 500000 typedef struct _HeapHeader { struct _HeapHeader *phhNext; struct _HeapHeader *phhPrev; PSZ pszFileWhereAllocated; UINT iLineWhereAllocated; UINT cbAllocated; PVOID pvAllocated; } HeapHeader, *PHeapHeader; void * __cdecl operator new(size_t nSize, PSZ pszWhichFile, UINT iWhichLine) { return AllocateMemory((UINT) nSize, FALSE, FALSE, pszWhichFile, iWhichLine); } void * __cdecl operator new(size_t nSize) { RonM_ASSERT(FALSE); // This routine should not be called by the debugging version // so long as everyone uses the New macro instead of the new // operator. return AllocateMemory((UINT) nSize, FALSE, FALSE); } void __cdecl operator delete(void *pbData) { ReleaseMemory(pbData); } #define BOOLEVAL(f) ((f) ? "TRUE" : "FALSE") static PHeapHeader phhAllocatedChain= NULL; PVOID AllocateMemory(UINT cb, BOOL fZeroMemory, BOOL fExceptions, PSZ pszWhichFile, UINT iWhichLine) { if (hheap == NULL) { hheap = GetProcessHeap(); RonM_ASSERT(hheap != NULL); if (hheap == NULL) return NULL; // GetSystemInfo(&si); } PVOID pv = NULL; PHeapHeader phh = NULL; fZeroMemory= TRUE; // for now... do { if (cb <= HEAP_SIZE_LIMIT) { UINT fHeapOptions= 0; if (fZeroMemory) fHeapOptions |= HEAP_ZERO_MEMORY; RonM_ASSERT(HeapValidate(hheap, 0, NULL)); pv= (PVOID) HeapAlloc(hheap, fHeapOptions, cb + sizeof(HeapHeader)); } else pv= VirtualAlloc(NULL, cb + sizeof(HeapHeader), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (pv) { phh= (PHeapHeader) pv; pv= PVOID(phh + 1); } else { if (fExceptions) RaiseException(STATUS_NO_MEMORY, EXCEPTION_NONCONTINUABLE, 0, NULL); else return NULL; } } while (pv == NULL); // Don't leave unhappy #ifdef _DEBUG phh->pszFileWhereAllocated = pszWhichFile; phh-> iLineWhereAllocated = iWhichLine; phh-> cbAllocated = cb; phh-> pvAllocated = pv; phh-> phhNext = phhAllocatedChain; phh-> phhPrev = NULL; if (phhAllocatedChain) phhAllocatedChain->phhPrev= phh; phhAllocatedChain= phh; ++cAllocs; cbAllocated += cb; if (pvTrap) RonM_ASSERT(pv != pvTrap); #else // _DEBUG phh->cbAllocated= cb; #endif // _DEBUG return pv; } PVOID AllocateMemory(UINT cb, BOOL fZeroMemory, BOOL fExceptions) { if (hheap == NULL) { hheap = GetProcessHeap(); RonM_ASSERT(hheap != NULL); if (hheap == NULL) return NULL; } PVOID pv = NULL; PHeapHeader phh = NULL; fZeroMemory= TRUE; // for now... do { if (cb <= HEAP_SIZE_LIMIT) { UINT fHeapOptions= 0; if (fZeroMemory) fHeapOptions |= HEAP_ZERO_MEMORY; RonM_ASSERT(HeapValidate(hheap, 0, NULL)); pv= (PVOID) HeapAlloc(hheap, fHeapOptions, cb + sizeof(HeapHeader)); } else pv= VirtualAlloc(NULL, cb + sizeof(HeapHeader), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (pv) { phh= (PHeapHeader) pv; pv= PVOID(phh + 1); } else { if (fExceptions) RaiseException(STATUS_NO_MEMORY, EXCEPTION_NONCONTINUABLE, 0, NULL); else return NULL; } } while (pv == NULL); // Don't leave unhappy phh->cbAllocated= cb; return pv; } #ifdef _DEBUG void ValidateHeap() { RonM_ASSERT(HeapValidate(hheap, 0, NULL)); } #endif // _DEBUG void ReleaseMemory(PVOID pv) { RonM_ASSERT(HeapValidate(hheap, 0, NULL)); PHeapHeader phh= PHeapHeader(pv) - 1; RonM_ASSERT(phh->pvAllocated == pv); #ifdef _DEBUG if (phh->phhNext) phh->phhNext->phhPrev = phh->phhPrev; if (phh->phhPrev) phh->phhPrev->phhNext = phh->phhNext; else phhAllocatedChain = phh->phhNext; #endif // _DEBUG pv= PVOID(phh); UINT cb= phh->cbAllocated; cbFreed+= cb; ++cFrees; if (cb <= HEAP_SIZE_LIMIT) HeapFree(hheap, 0, pv); else VirtualFree(pv, 0, MEM_RELEASE); RonM_ASSERT(HeapValidate(hheap, 0, NULL)); } #ifdef _DEBUG void DumpResidualAllocations() { char acDebugBuff[256]; wsprintf(acDebugBuff, "%u Orphan Allocations (%u byte total):\n", cAllocs - cFrees, cbAllocated - cbFreed); OutputDebugString(acDebugBuff); UINT iOrphan= 0; for (PHeapHeader phh= phhAllocatedChain; phh; phh= phh->phhNext) { wsprintf(acDebugBuff, " [%u]: %10u Bytes @ 0x%08x Allocated in %s[%u]\n", iOrphan++, phh->cbAllocated, UINT_PTR(phh->pvAllocated), phh->pszFileWhereAllocated, phh->iLineWhereAllocated ); OutputDebugString(acDebugBuff); } } #endif _DEBUG void LiberateHeap() { if (hheap == NULL) return; #ifdef _DEBUG if (phhAllocatedChain) DumpResidualAllocations(); #endif // _DEBUG // BOOL fDone= HeapDestroy(hheap); #ifdef _DEBUG UINT iReason= GetLastError(); #endif // _DEBUG // RonM_ASSERT(fDone); hheap = NULL; }