You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
199 lines
4.3 KiB
199 lines
4.3 KiB
// memmgr.c
|
|
//
|
|
// This file contains definitions for the memory management.
|
|
// Implementation details may change so beware of relying on internal details.
|
|
//
|
|
|
|
#include "private.h"
|
|
#include "memmgr.h"
|
|
|
|
#ifdef DEBUG
|
|
int cAllocMem = 0; // Amount of memory alloced
|
|
int cAlloc = 0; // Count of allocs outstanding
|
|
int cAllocMaxMem = 0; // Max amount of memory ever alloced.
|
|
#endif
|
|
|
|
#ifdef DEBUG
|
|
int gFailure = 0;
|
|
#endif
|
|
|
|
/******************************Public*Routine******************************\
|
|
* ExternAlloc
|
|
*
|
|
* This guy keeps the size in the first long so we can fake a realloc. Lot's
|
|
* of debug checking for heap overwrites.
|
|
*
|
|
* History:
|
|
* 19-Nov-1996 -by- Patrick Haluptzok patrickh
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
void *ExternAlloc(DWORD cb)
|
|
{
|
|
long *pl;
|
|
DWORD cbAlloc;
|
|
|
|
#ifdef DEBUG
|
|
#ifndef WINCE
|
|
//
|
|
// If gFailure is 0 nothing happens, if it's non-zero we
|
|
// fail 1 in gFailure allocations.
|
|
//
|
|
|
|
if (gFailure)
|
|
{
|
|
if (((rand() * gFailure) / (RAND_MAX + 1)) == 0)
|
|
{
|
|
return (void *) NULL;
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
// Since we can't use realloc on WINCE, we need to save the original size for memcpy
|
|
// in our own realloc function.
|
|
|
|
cbAlloc = cb + 4;
|
|
|
|
#ifdef DEBUG
|
|
cbAlloc += 3; // round it up to DWORD boundary
|
|
cbAlloc &= ~3;
|
|
cbAlloc += 8; // write size at begining and overwrite detector at begining and end
|
|
#endif
|
|
|
|
pl = (long *) malloc(cbAlloc);
|
|
if (pl == (long *) NULL)
|
|
return pl;
|
|
|
|
// Stamp this baby full of invalid bytes so code that relies on 0's in it are sniffed out.
|
|
|
|
#ifdef DEBUG
|
|
memset(pl,0xff,cbAlloc);
|
|
#endif
|
|
|
|
// OK, tuck the object size away at the begining
|
|
|
|
*(pl++) = cb;
|
|
|
|
#ifdef DEBUG
|
|
*(pl++) = 0xDEADBEEF;
|
|
pl[(cbAlloc / 4) - 3] = 0xDEADBEEF;
|
|
cAlloc++;
|
|
cAllocMem += cb;
|
|
|
|
if (cAllocMem > cAllocMaxMem)
|
|
{
|
|
TCHAR szDebug[128];
|
|
cAllocMaxMem = cAllocMem;
|
|
wsprintf(szDebug, TEXT("cAllocMaxMem = %d \r\n"), cAllocMaxMem);
|
|
OutputDebugString(szDebug);
|
|
}
|
|
#endif
|
|
|
|
return pl;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* ExternRealloc
|
|
*
|
|
* Well this not good but we want the same exact code on NT and WINCE and
|
|
* we can't find a way to use the flags and have Realloc work the same on
|
|
* both. Realloc is a very infrequent event so this work for us.
|
|
*
|
|
* History:
|
|
* 19-Nov-1996 -by- Patrick Haluptzok patrickh
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
void *ExternRealloc(void *pv, DWORD cbNew)
|
|
{
|
|
void *pvNew = ExternAlloc(cbNew);
|
|
|
|
if (pv && pvNew)
|
|
{
|
|
long *pl;
|
|
DWORD cb;
|
|
|
|
pl = (long *) pv;
|
|
|
|
#ifdef DEBUG
|
|
pl--;
|
|
#endif
|
|
|
|
cb = (DWORD) *(--pl);
|
|
memcpy(pvNew, pv, min(cbNew, cb));
|
|
ExternFree(pv);
|
|
}
|
|
|
|
return pvNew;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* ExternFree
|
|
*
|
|
* Free up the memory, in debug mode check for heap corruption !
|
|
*
|
|
* History:
|
|
* 19-Nov-1996 -by- Patrick Haluptzok patrickh
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
void ExternFree(void *pv)
|
|
{
|
|
long *pl;
|
|
|
|
// We now allow freeing of null pointers
|
|
|
|
if (pv == (void *) NULL)
|
|
return;
|
|
|
|
pl = (long *) pv;
|
|
pl--;
|
|
|
|
#ifdef DEBUG
|
|
{
|
|
int cbAlloc;
|
|
|
|
// Check nothing has been stepped on.
|
|
|
|
pl--;
|
|
cbAlloc = *pl;
|
|
cAllocMem -= cbAlloc;
|
|
cbAlloc = (cbAlloc + 11) & ~3;
|
|
cAlloc--;
|
|
}
|
|
#endif
|
|
|
|
free(pl);
|
|
}
|
|
|
|
char *Externstrdup( const char *strSource )
|
|
{
|
|
int nLen = 0;
|
|
char* pszOut = NULL;
|
|
|
|
// fail immediately on a null pointer
|
|
if (NULL == strSource)
|
|
return NULL;
|
|
|
|
// get the length of the ansi string
|
|
nLen = strlen(strSource) * sizeof(char);
|
|
|
|
// fail on a 0 length string
|
|
// @todo(petewil) - is this right, or return 0 length string instead?
|
|
if (0 == nLen)
|
|
return NULL;
|
|
|
|
// allow room for a trailing null
|
|
nLen += sizeof(char);
|
|
|
|
// allocate space for the string
|
|
pszOut = (char*)ExternAlloc(nLen);
|
|
|
|
if (NULL == pszOut)
|
|
return NULL;
|
|
|
|
// copy the string into the buffer provided
|
|
StringCchCopyA(pszOut, nLen, strSource);
|
|
return pszOut;
|
|
}
|