//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1997. // // File: N C M E M . C P P // // Contents: Common memory management routines. // // Notes: // // Author: shaunco 24 Mar 1997 // deonb 2 Jan 2002 // // // Our memory allocations rules are: // * Most of our memory allocators do NOT throw exceptions but instead return NULL. // This includes MemAlloc, operator new, operator new[], calloc & malloc. // * Anything explicitly allocated using: p = new(throwonfail) CClass(), will raise a bad_alloc on failure. // * STL: // #ifdef (USE_CUSTOM_STL_ALLOCATOR) // The STL memory allocator will raise a bad_alloc C++ exception on low memory. // (Note, not an SEH exception!). // #else // STL will raise an access violation exception after out-of-memory occurred and // it tries to use the memory. // #endif // * Currently USE_CUSTOM_STL_ALLOCATOR is defined in our makefile.inc // //---------------------------------------------------------------------------- #include #pragma hdrstop #include "ncdebug.h" #include "ncmem.h" // Debug limit for single memory allocation (16 MB) #define MAX_DEBUG_ALLOC 16 * 1048576 // This global heap handle will be set to the process heap when the // first request to allocate memory through MemAlloc is made. // HANDLE g_hHeap = NULL; //+--------------------------------------------------------------------------- // // Function: MemAlloc // // Purpose: NetConfig's memory allocator // // Arguments: // cb [in] Count of bytes to allocate. // // Returns: Pointer to allocated memory, or NULL if failed. // // Author: deonb 2 Jan 2002 // // Notes: Free the returned buffer with MemFree. // Will ASSERT in debug if attempt to allocate more than MAX_DEBUG_ALLOC (Currently 16 MB) // // We COULD extend this to include a primitive buffer overrun check, but it would require us // to put the size of the allocated block in the beginning of the buffer, and would make things like // allocating with MemAlloc but freeing it with HeapFree fail. // PageHeap / AVRF is better suited for this purpose since it works directly with the RTL allocator. // VOID* MemAlloc ( size_t cb) throw() { AssertSz(cb < MAX_DEBUG_ALLOC, "Suspicious request for a lot of memory"); if (!g_hHeap) { // Don't trace in this part of the function. It will likely recurse. g_hHeap = GetProcessHeap(); if (!g_hHeap) { AssertSz(FALSE, "MemAlloc could not get the process heap."); return NULL; } } LPVOID lpAlloc = HeapAlloc (g_hHeap, 0, cb); if (!lpAlloc) { TraceTag(ttidError, "MemAlloc failed request for %d bytes from:", cb); TraceStack(ttidError); } return lpAlloc; } //+--------------------------------------------------------------------------- // // Function: MemFree // // Purpose: NetConfig's memory de-allocator // // Arguments: // pv [in] Pointer to previously allocated memory // // Returns: none // // Author: deonb 2 Jan 2002 // // Notes: Free the returned buffer from MemAlloc. // Don't trace in this function. It will recurse. VOID MemFree ( VOID* pv) throw() { if (pv) { if (!g_hHeap) { AssertSz(FALSE, "Suspicious call to MemFree before MemAlloc"); g_hHeap = GetProcessHeap(); if (!g_hHeap) { return; } } HeapFree (g_hHeap, 0, pv); } } //+--------------------------------------------------------------------------- // // Function: HrMalloc // // Purpose: HRESULT returning version of malloc. // // Arguments: // cb [in] Count of bytes to allocate. // ppv [out] Address of returned allocation. // // Returns: S_OK or E_OUTOFMEMORY; // // Author: shaunco 31 Mar 1998 // // Notes: Free the returned buffer with free. // HRESULT HrMalloc ( size_t cb, PVOID* ppv) throw() { Assert (ppv); HRESULT hr = S_OK; *ppv = MemAlloc (cb); if (!*ppv) { hr = E_OUTOFMEMORY; TraceHr (ttidError, FAL, hr, FALSE, "HrMalloc failed request for %d bytes from:", cb); TraceStack(ttidError); } return hr; } namespace std { // report a length_error void __cdecl _Xlen() { _THROW(length_error, "string too long"); } // report an out_of_range error void __cdecl _Xran() { _THROW(out_of_range, "invalid string position"); } } //+--------------------------------------------------------------------------- // CRT memory function overloads // const throwonfail_t throwonfail; VOID* __cdecl operator new ( size_t cb, const throwonfail_t& ) throw (std::bad_alloc) { LPVOID pv = MemAlloc (cb); if (!pv) { throw std::bad_alloc(); } return pv; } VOID __cdecl operator delete ( void* pv, const throwonfail_t&) throw () { MemFree (pv); } const extrabytes_t extrabytes; VOID* __cdecl operator new ( size_t cb, const extrabytes_t&, size_t cbExtra) throw() { return MemAlloc (cb + cbExtra); } VOID __cdecl operator delete( void* pv, const extrabytes_t&, size_t cbExtra) throw() { MemFree (pv); } VOID* __cdecl operator new ( size_t cb) throw() { return MemAlloc (cb); } VOID* __cdecl operator new ( size_t cb, std::nothrow_t const &) throw() { return MemAlloc (cb); } VOID* __cdecl operator new[] ( size_t cb) throw() { return MemAlloc (cb); } VOID __cdecl operator delete ( VOID* pv) throw() { MemFree (pv); } VOID __cdecl operator delete[] ( VOID* pv) throw() { MemFree (pv); }