git-svn-id: https://svn.code.sf.net/p/flaim/code/trunk@192 0109f412-320b-0410-ab79-c3e0c5ffbbe6
1465 lines
32 KiB
C++
1465 lines
32 KiB
C++
//-------------------------------------------------------------------------
|
|
// Desc: Memory allocation routines.
|
|
// Tabs: 3
|
|
//
|
|
// Copyright (c) 1991,1993,1995-2006 Novell, Inc. All Rights Reserved.
|
|
//
|
|
// This program is free software; you can redistribute it and/or
|
|
// modify it under the terms of version 2 of the GNU General Public
|
|
// License as published by the Free Software Foundation.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program; if not, contact Novell, Inc.
|
|
//
|
|
// To contact Novell about this file by physical or electronic mail,
|
|
// you may find current contact information at www.novell.com
|
|
//
|
|
// $Id: flalloc.cpp 12329 2006-01-20 17:49:30 -0700 (Fri, 20 Jan 2006) ahodgkinson $
|
|
//-------------------------------------------------------------------------
|
|
|
|
#include "flaimsys.h"
|
|
|
|
#undef f_free
|
|
#undef f_alloc
|
|
#undef f_calloc
|
|
#undef f_realloc
|
|
#undef f_recalloc
|
|
|
|
#ifdef FLM_NLM
|
|
extern "C"
|
|
{
|
|
extern LONG gv_lAllocRTag;
|
|
}
|
|
#endif
|
|
|
|
#ifdef FLM_UNIX
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#ifdef HAVE_DLADDR
|
|
#include <dlfcn.h>
|
|
#endif
|
|
#include <stdlib.h>
|
|
|
|
#endif
|
|
|
|
#define F_GET_ALLOC_PTR( pDataPtr) \
|
|
(FLMBYTE *)((FLMBYTE *)(pDataPtr) - sizeof( F_MEM_HDR))
|
|
|
|
#define F_GET_DATA_PTR( pAllocPtr) \
|
|
(FLMBYTE *)((FLMBYTE *)(pAllocPtr) + sizeof( F_MEM_HDR))
|
|
|
|
#define F_GET_MEM_DATA_SIZE( pDataPtr) \
|
|
(((F_MEM_HDR *)(F_GET_ALLOC_PTR( pDataPtr)))->uiDataSize)
|
|
|
|
// Picket fence
|
|
|
|
#define F_PICKET_FENCE "FFFFFFFF"
|
|
|
|
#if defined( FLM_DEBUG)
|
|
#define F_PICKET_FENCE_SIZE 8
|
|
#else
|
|
#define F_PICKET_FENCE_SIZE 0
|
|
#endif
|
|
|
|
#define MEM_PTR_INIT_ARRAY_SIZE 512
|
|
#define MEM_MAX_STACK_WALK_DEPTH 32
|
|
|
|
// If stack tracking is on, leak checking also
|
|
// needs to be on.
|
|
|
|
#ifndef FLM_DEBUG
|
|
#ifdef DEBUG_SIM_OUT_OF_MEM
|
|
#undef DEBUG_SIM_OUT_OF_MEM
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef FLM_DEBUG
|
|
|
|
// Local function prototypes
|
|
|
|
FSTATIC FLMBOOL initMemTracking(
|
|
void);
|
|
|
|
FSTATIC void saveMemTrackingInfo(
|
|
F_MEM_HDR * pHdr);
|
|
|
|
FSTATIC void updateMemTrackingInfo(
|
|
F_MEM_HDR * pHdr);
|
|
|
|
FSTATIC void freeMemTrackingInfo(
|
|
FLMBOOL bMutexAlreadyLocked,
|
|
FLMUINT uiId,
|
|
FLMUINT * puiStack);
|
|
|
|
#ifdef DEBUG_SIM_OUT_OF_MEM
|
|
|
|
//one of every OUT_OF_MEM_FREQUENCY calls will fail
|
|
|
|
#define OUT_OF_MEM_FREQUENCY 40000
|
|
|
|
//OUT_OF_MEM_SEQUENCE_LENGTH calls in a row will fail
|
|
|
|
#define OUT_OF_MEM_SEQUENCE_LENGTH 10
|
|
|
|
FLMBOOL SimulateOutOfMemory()
|
|
{
|
|
if (
|
|
//is the flag turned on
|
|
(gv_FlmSysData.uiOutOfMemSimEnabledFlag ==
|
|
(FLMUINT)OUT_OF_MEM_SIM_ENABLED_FLAG) &&
|
|
|
|
//continuing a sequence of failures
|
|
((gv_FlmSysData.uiSimOutOfMemFailSequence > 0) ||
|
|
|
|
//failing randomly for the first time, and starting a new sequence
|
|
(f_randomChoice( &gv_FlmSysData.memSimRandomGen, 0, OUT_OF_MEM_FREQUENCY) == 0)))
|
|
{
|
|
gv_FlmSysData.uiSimOutOfMemFailTotal++;
|
|
gv_FlmSysData.uiSimOutOfMemFailSequence++;
|
|
//if reached the end of failure sequence, reset back to 0 so the
|
|
//sequence will cease
|
|
if ( gv_FlmSysData.uiSimOutOfMemFailSequence >= OUT_OF_MEM_SEQUENCE_LENGTH)
|
|
{
|
|
gv_FlmSysData.uiSimOutOfMemFailSequence = 0;
|
|
}
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
#endif //#ifdef DEBUG_SIM_OUT_OF_MEM
|
|
|
|
#if defined( FLM_NLM)
|
|
|
|
void * memGetEBP(void);
|
|
|
|
#ifdef __MWERKS__
|
|
|
|
void * memGetEBP(void)
|
|
{
|
|
__asm
|
|
{
|
|
mov eax,[ebp]
|
|
}
|
|
}
|
|
|
|
#else
|
|
|
|
#pragma aux memGetEBP = "mov eax,ebp";
|
|
|
|
#endif
|
|
|
|
void * memValueAtStackOffset(
|
|
void * pos,
|
|
int offset);
|
|
|
|
#ifdef __MWERKS__
|
|
|
|
void * memValueAtStackOffset( void *, int)
|
|
{
|
|
__asm
|
|
{
|
|
mov eax,[ebp+0x8]
|
|
mov ebx,[ebp+0xC]
|
|
mov eax,ss:[eax+ebx]
|
|
}
|
|
}
|
|
|
|
#else
|
|
|
|
#pragma aux memValueAtStackOffset = "mov eax,ss:[eax+ebx]" parm [eax] [ebx];
|
|
|
|
#endif
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
FLMUINT * memWalkStack( void)
|
|
{
|
|
FLMUINT uiLoop;
|
|
FLMUINT uiRtnAddr;
|
|
FLMUINT uiEbp = (FLMUINT) memGetEBP();
|
|
FLMUINT uiAddresses [MEM_MAX_STACK_WALK_DEPTH + 1];
|
|
FLMUINT * puiAddresses;
|
|
|
|
uiEbp = (FLMUINT) memValueAtStackOffset( (void *)uiEbp, 0);
|
|
uiRtnAddr = (FLMUINT) memValueAtStackOffset( (void *)uiEbp, 4);
|
|
|
|
for( uiLoop = 0; uiLoop < MEM_MAX_STACK_WALK_DEPTH; uiLoop++)
|
|
{
|
|
FLMUINT uiOldEbp;
|
|
|
|
uiAddresses [uiLoop] = uiRtnAddr;
|
|
|
|
if( !uiEbp)
|
|
{
|
|
break;
|
|
}
|
|
|
|
uiOldEbp = uiEbp;
|
|
uiEbp = (FLMUINT) memValueAtStackOffset( (void *)uiEbp, 0);
|
|
|
|
if (!uiEbp || uiEbp <= uiOldEbp || uiEbp > uiOldEbp + 5000)
|
|
{
|
|
break;
|
|
}
|
|
|
|
uiRtnAddr = (FLMUINT) memValueAtStackOffset( (void *) uiEbp, 4);
|
|
}
|
|
|
|
uiAddresses[ uiLoop] = 0;
|
|
|
|
if( (puiAddresses = (FLMUINT *)os_malloc(
|
|
sizeof( FLMUINT) * (uiLoop+1))) != NULL)
|
|
{
|
|
f_memcpy( puiAddresses, &uiAddresses [0],
|
|
sizeof( FLMUINT) * (uiLoop + 1));
|
|
}
|
|
|
|
return( puiAddresses);
|
|
}
|
|
|
|
#elif defined( FLM_WIN)
|
|
|
|
/********************************************************************
|
|
Desc: Reads NSIZE bytes of memory from LPBASEADDRESS
|
|
*********************************************************************/
|
|
static BOOL CALLBACK ReadProcMemory(
|
|
HANDLE,
|
|
DWORD64 lpBaseAddress,
|
|
PVOID lpBuffer,
|
|
DWORD nSize,
|
|
LPDWORD lpNumberOfBytesRead)
|
|
{
|
|
static HANDLE hRealProcess = GetCurrentProcess();
|
|
SIZE_T bytesRead = 0;
|
|
BOOL rv = ReadProcessMemory(hRealProcess,
|
|
(const void *)((FLMUINT)lpBaseAddress & 0xFFFFFFFF),
|
|
lpBuffer, SIZE_T(nSize), &bytesRead);
|
|
|
|
if (lpNumberOfBytesRead)
|
|
{
|
|
*lpNumberOfBytesRead = DWORD(bytesRead & 0xFFFFFFFF);
|
|
}
|
|
|
|
return( rv);
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Walk the call stack.
|
|
*********************************************************************/
|
|
FLMUINT * memWalkStack()
|
|
{
|
|
STACKFRAME64 stackFrame;
|
|
DWORD machineType;
|
|
FLMUINT uiLoop;
|
|
FLMUINT uiAddresses [MEM_MAX_STACK_WALK_DEPTH + 1];
|
|
FLMUINT * puiAddresses;
|
|
HANDLE hProcess = GetCurrentProcess();
|
|
FLMUINT uiAddrCount;
|
|
const void * pc;
|
|
const void * fp;
|
|
|
|
__asm
|
|
{
|
|
call $ + 5
|
|
pop eax
|
|
mov [pc], eax
|
|
mov [fp], ebp
|
|
}
|
|
|
|
#ifdef FLM_64BIT
|
|
machineType = IMAGE_FILE_MACHINE_IA64;
|
|
#else
|
|
machineType = IMAGE_FILE_MACHINE_I386;
|
|
#endif
|
|
|
|
f_memset( &stackFrame, 0, sizeof( stackFrame));
|
|
|
|
stackFrame.AddrPC.Offset = DWORD((FLMUINT)pc);
|
|
stackFrame.AddrPC.Mode = AddrModeFlat;
|
|
stackFrame.AddrFrame.Offset = DWORD((FLMUINT)fp);
|
|
stackFrame.AddrFrame.Mode = AddrModeFlat;
|
|
|
|
f_mutexLock( gv_FlmSysData.hMemTrackingMutex);
|
|
|
|
// We have already processed the address inside memWalkStack
|
|
|
|
uiAddrCount = 1;
|
|
uiLoop = 0;
|
|
for (;;)
|
|
{
|
|
if( !StackWalk64( machineType, hProcess, 0, &stackFrame,
|
|
0, ReadProcMemory, SymFunctionTableAccess64, SymGetModuleBase64, 0))
|
|
{
|
|
break;
|
|
}
|
|
|
|
if( !stackFrame.AddrFrame.Offset)
|
|
{
|
|
break;
|
|
}
|
|
|
|
// Skip the first two addresses. These represent the following:
|
|
// 1) memWalkStack
|
|
// 2) saveMemTrackingInfo or updateMemTrackingInfo
|
|
// We don't need to see them in the stack trace.
|
|
|
|
uiAddrCount++;
|
|
if (uiAddrCount > 2)
|
|
{
|
|
uiAddresses [uiLoop] = (FLMUINT)stackFrame.AddrReturn.Offset;
|
|
uiLoop++;
|
|
if (uiLoop == MEM_MAX_STACK_WALK_DEPTH)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
f_mutexUnlock( gv_FlmSysData.hMemTrackingMutex);
|
|
|
|
uiAddresses [uiLoop] = 0;
|
|
if ((puiAddresses = (FLMUINT *)os_malloc(
|
|
sizeof( FLMUINT) * (uiLoop+1))) != NULL)
|
|
{
|
|
f_memcpy( puiAddresses, &uiAddresses [0], sizeof( FLMUINT) * (uiLoop + 1));
|
|
}
|
|
return( puiAddresses);
|
|
}
|
|
#else
|
|
FLMUINT * memWalkStack()
|
|
{
|
|
return( NULL);
|
|
}
|
|
#endif
|
|
|
|
/********************************************************************
|
|
Desc: Initialize memory tracking
|
|
*********************************************************************/
|
|
FSTATIC FLMBOOL initMemTracking( void)
|
|
{
|
|
RCODE rc;
|
|
F_MUTEX memMutex;
|
|
|
|
if (!gv_FlmSysData.bMemTrackingInitialized && !gv_FlmSysData.uiInitThreadId)
|
|
{
|
|
gv_FlmSysData.uiInitThreadId = f_threadId();
|
|
rc = f_mutexCreate( &memMutex);
|
|
f_sleep( 50);
|
|
|
|
// Only set to initialized if we were the last thread
|
|
// to set gv_FlmSysData.uiInitThreadId
|
|
|
|
if (f_threadId() == gv_FlmSysData.uiInitThreadId)
|
|
{
|
|
if (RC_OK( rc))
|
|
{
|
|
gv_FlmSysData.hMemTrackingMutex = memMutex;
|
|
}
|
|
else
|
|
{
|
|
gv_FlmSysData.hMemTrackingMutex = F_MUTEX_NULL;
|
|
}
|
|
#ifdef FLM_WIN
|
|
SymSetOptions( SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS);
|
|
gv_FlmSysData.hMemProcess = GetCurrentProcess();
|
|
SymInitialize( gv_FlmSysData.hMemProcess, NULL, TRUE);
|
|
#endif
|
|
gv_FlmSysData.bMemTrackingInitialized = TRUE;
|
|
}
|
|
else
|
|
{
|
|
if (RC_OK( rc))
|
|
{
|
|
f_mutexDestroy( &memMutex);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Go into a loop until we see initialized flag set to TRUE
|
|
// Could be another thread that is doing it.
|
|
|
|
while (!gv_FlmSysData.bMemTrackingInitialized)
|
|
{
|
|
f_sleep( 10);
|
|
}
|
|
return( (gv_FlmSysData.hMemTrackingMutex != F_MUTEX_NULL) ? TRUE : FALSE);
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Save memory tracking information - called on alloc or realloc.
|
|
*********************************************************************/
|
|
FSTATIC void saveMemTrackingInfo(
|
|
F_MEM_HDR * pHdr)
|
|
{
|
|
FLMUINT uiNewCnt;
|
|
FLMUINT uiId;
|
|
void ** pNew;
|
|
|
|
if (gv_FlmSysData.bTrackLeaks && initMemTracking())
|
|
{
|
|
f_mutexLock( gv_FlmSysData.hMemTrackingMutex);
|
|
|
|
// See if there is enough room in the array
|
|
|
|
if (gv_FlmSysData.uiMemNumPtrs == gv_FlmSysData.uiMemTrackingPtrArraySize)
|
|
{
|
|
|
|
// If array is not initialized, use initial count. Otherwise
|
|
// double the size.
|
|
|
|
uiNewCnt = (FLMUINT)((!gv_FlmSysData.uiMemTrackingPtrArraySize)
|
|
? MEM_PTR_INIT_ARRAY_SIZE
|
|
: gv_FlmSysData.uiMemTrackingPtrArraySize * 2);
|
|
if ((pNew = (void **)os_malloc( sizeof( void *) * uiNewCnt)) != NULL)
|
|
{
|
|
|
|
// Copy the pointers from the old array, if any,
|
|
// into the newly allocated array.
|
|
|
|
if (gv_FlmSysData.uiMemTrackingPtrArraySize)
|
|
{
|
|
f_memcpy( pNew, gv_FlmSysData.ppvMemTrackingPtrs,
|
|
sizeof( void *) * gv_FlmSysData.uiMemTrackingPtrArraySize);
|
|
os_free( gv_FlmSysData.ppvMemTrackingPtrs);
|
|
}
|
|
f_memset( &pNew [gv_FlmSysData.uiMemTrackingPtrArraySize], 0,
|
|
sizeof( void *) * (uiNewCnt - gv_FlmSysData.uiMemTrackingPtrArraySize));
|
|
gv_FlmSysData.ppvMemTrackingPtrs = pNew;
|
|
gv_FlmSysData.uiMemTrackingPtrArraySize = uiNewCnt;
|
|
}
|
|
}
|
|
|
|
// If we are still full, we were not able to reallocate memory, so we
|
|
// do nothing.
|
|
|
|
if (gv_FlmSysData.uiMemNumPtrs == gv_FlmSysData.uiMemTrackingPtrArraySize)
|
|
{
|
|
pHdr->uiAllocationId = 0;
|
|
}
|
|
else
|
|
{
|
|
// Find an empty slot - there has to be one!
|
|
|
|
uiId = gv_FlmSysData.uiMemNextPtrSlotToUse;
|
|
while (gv_FlmSysData.ppvMemTrackingPtrs [uiId])
|
|
{
|
|
if (++uiId == gv_FlmSysData.uiMemTrackingPtrArraySize)
|
|
{
|
|
uiId = 0;
|
|
}
|
|
}
|
|
|
|
// Allocation ID in the header is offset by one to avoid
|
|
// using a value of zero.
|
|
|
|
pHdr->uiAllocationId = uiId + 1;
|
|
gv_FlmSysData.ppvMemTrackingPtrs [uiId] = pHdr;
|
|
gv_FlmSysData.uiMemNumPtrs++;
|
|
if ((gv_FlmSysData.uiMemNextPtrSlotToUse = uiId + 1) ==
|
|
gv_FlmSysData.uiMemTrackingPtrArraySize)
|
|
{
|
|
gv_FlmSysData.uiMemNextPtrSlotToUse = 0;
|
|
}
|
|
}
|
|
pHdr->uiAllocCnt = ++gv_FlmSysData.uiAllocCnt;
|
|
f_mutexUnlock( gv_FlmSysData.hMemTrackingMutex);
|
|
}
|
|
else
|
|
{
|
|
pHdr->uiAllocationId = 0;
|
|
pHdr->uiAllocCnt = 0;
|
|
}
|
|
|
|
// Follow the stack.
|
|
|
|
if (gv_FlmSysData.bTrackLeaks && gv_FlmSysData.bStackWalk)
|
|
{
|
|
pHdr->puiStack = memWalkStack();
|
|
}
|
|
else
|
|
{
|
|
pHdr->puiStack = NULL;
|
|
}
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Update memory tracking information - called after realloc
|
|
*********************************************************************/
|
|
FSTATIC void updateMemTrackingInfo(
|
|
F_MEM_HDR * pHdr)
|
|
{
|
|
if (pHdr->puiStack)
|
|
{
|
|
os_free( pHdr->puiStack);
|
|
pHdr->puiStack = NULL;
|
|
}
|
|
if (gv_FlmSysData.bTrackLeaks && gv_FlmSysData.bStackWalk)
|
|
{
|
|
pHdr->puiStack = memWalkStack();
|
|
}
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Free memory tracking information - called on free.
|
|
*********************************************************************/
|
|
FSTATIC void freeMemTrackingInfo(
|
|
FLMBOOL bMutexAlreadyLocked,
|
|
FLMUINT uiId,
|
|
FLMUINT * puiStack
|
|
)
|
|
{
|
|
if (uiId)
|
|
{
|
|
// NOTE: If uiId is non-zero, it means we had to have
|
|
// successfully initialized, so we are guaranteed to
|
|
// have a mutex.
|
|
|
|
if ( !bMutexAlreadyLocked)
|
|
{
|
|
f_mutexLock( gv_FlmSysData.hMemTrackingMutex);
|
|
}
|
|
|
|
// Allocation ID in the header is offset by one so that it
|
|
// is never zero - a value of zero means that the allocation
|
|
// does not have a slot for tracking it in the array.
|
|
|
|
gv_FlmSysData.ppvMemTrackingPtrs [uiId - 1] = NULL;
|
|
flmAssert( gv_FlmSysData.uiMemNumPtrs);
|
|
gv_FlmSysData.uiMemNumPtrs--;
|
|
|
|
if ( !bMutexAlreadyLocked)
|
|
{
|
|
f_mutexUnlock( gv_FlmSysData.hMemTrackingMutex);
|
|
}
|
|
}
|
|
|
|
// Free the stack information, if any.
|
|
|
|
if (puiStack)
|
|
{
|
|
os_free( puiStack);
|
|
}
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Log memory leaks.
|
|
*********************************************************************/
|
|
void logMemLeak(
|
|
F_MEM_HDR * pHdr)
|
|
{
|
|
char szMessageBuffer [1024];
|
|
char * pszTmp = &szMessageBuffer [0];
|
|
F_FileHdl * pFileHdl = NULL;
|
|
FLMBOOL bOldTrackLeaks = gv_FlmSysData.bTrackLeaks;
|
|
|
|
gv_FlmSysData.bTrackLeaks = FALSE; // This ensures that any future
|
|
// allocations (for instance,
|
|
// allocating the file handle for the
|
|
// memtest.ert file) will not try to
|
|
// lock the mem tracking mutex.
|
|
|
|
|
|
|
|
// Format message to be logged.
|
|
|
|
f_strcpy( pszTmp, "Abort=Debug, Retry=Continue, Ignore=Don't Show\r\n");
|
|
while (*pszTmp)
|
|
{
|
|
pszTmp++;
|
|
}
|
|
#if defined( FLM_64BIT)
|
|
f_sprintf( pszTmp, "Unfreed Pointer: 0x%016I64x\r\n", (FLMUINT)(&pHdr [1]));
|
|
#else
|
|
f_sprintf( pszTmp, "Unfreed Pointer: 0x%08x\r\n",
|
|
(unsigned)((FLMUINT)(&pHdr [1])));
|
|
#endif
|
|
while (*pszTmp)
|
|
{
|
|
pszTmp++;
|
|
}
|
|
|
|
if (pHdr->pszFileName)
|
|
{
|
|
f_sprintf( pszTmp, "Source: %s, Line#: %u\r\n", pHdr->pszFileName,
|
|
(unsigned)pHdr->iLineNumber);
|
|
while (*pszTmp)
|
|
{
|
|
pszTmp++;
|
|
}
|
|
}
|
|
|
|
if (pHdr->uiAllocCnt)
|
|
{
|
|
f_sprintf( pszTmp, "Malloc #: %u\r\n", (unsigned)pHdr->uiAllocCnt);
|
|
while (*pszTmp)
|
|
{
|
|
pszTmp++;
|
|
}
|
|
}
|
|
f_sprintf( pszTmp, "Size: %u bytes\r\n", (unsigned)pHdr->uiDataSize);
|
|
while (*pszTmp)
|
|
{
|
|
pszTmp++;
|
|
}
|
|
|
|
if (pHdr->puiStack)
|
|
{
|
|
FLMUINT * puiStack = pHdr->puiStack;
|
|
FLMUINT uiLen = pszTmp - szMessageBuffer;
|
|
char szFuncName [200];
|
|
char * pszFuncName;
|
|
#ifdef FLM_WIN
|
|
IMAGEHLP_SYMBOL * pImgHlpSymbol;
|
|
|
|
pImgHlpSymbol = (IMAGEHLP_SYMBOL *)os_malloc(
|
|
sizeof( IMAGEHLP_SYMBOL) + 100);
|
|
#endif
|
|
|
|
while (*puiStack)
|
|
{
|
|
szFuncName [0] = 0;
|
|
#if defined( FLM_WIN)
|
|
if (pImgHlpSymbol)
|
|
{
|
|
#ifdef FLM_64BIT
|
|
DWORD64 udDisplacement;
|
|
#else
|
|
DWORD udDisplacement;
|
|
#endif
|
|
|
|
pImgHlpSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL);
|
|
pImgHlpSymbol->Address = *puiStack;
|
|
pImgHlpSymbol->MaxNameLength = 100;
|
|
|
|
if (SymGetSymFromAddr( gv_FlmSysData.hMemProcess, *puiStack,
|
|
&udDisplacement, pImgHlpSymbol))
|
|
{
|
|
f_sprintf( szFuncName, "\t%s + %X\r\n",
|
|
(&pImgHlpSymbol->Name [0]),
|
|
udDisplacement);
|
|
}
|
|
}
|
|
#elif defined( FLM_NLM)
|
|
{
|
|
szFuncName [0] = '\t';
|
|
GetClosestSymbol( (BYTE *)(&szFuncName[1]), (LONG)(*puiStack));
|
|
}
|
|
#else
|
|
|
|
#ifdef HAVE_DLADDR
|
|
{
|
|
Dl_info dlip;
|
|
|
|
if (dladdr( (void *)(*puiStack), &dlip) != 0 && dlip.dli_sname)
|
|
{
|
|
const char * pszFileName;
|
|
if (dlip.dli_saddr != (void *)(*puiStack))
|
|
{
|
|
pszFileName = strrchr(dlip.dli_fname, '/');
|
|
if (!pszFileName)
|
|
{
|
|
pszFileName = dlip.dli_fname;
|
|
}
|
|
else
|
|
{
|
|
pszFileName++; // skip over slash
|
|
}
|
|
f_sprintf( szFuncName, "\t0x%08x (%s)\r\n",
|
|
(unsigned)(*puiStack), pszFileName);
|
|
}
|
|
else
|
|
{
|
|
f_sprintf( szFuncName, "\t%s\r\n", dlip.dli_sname);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#endif
|
|
|
|
// If szFuncName [0] is zero, we didn't find a name, so we
|
|
// just output the address in HEX.
|
|
|
|
if (!szFuncName [0])
|
|
{
|
|
f_sprintf( szFuncName, "\t0x%08X\r\n", (unsigned)*puiStack );
|
|
}
|
|
|
|
// Output whatever portion of the name will fit into the
|
|
// message buffer.
|
|
|
|
pszFuncName = &szFuncName [0];
|
|
while (*pszFuncName && uiLen < sizeof( szMessageBuffer) - 1)
|
|
{
|
|
*pszTmp++ = *pszFuncName++;
|
|
uiLen++;
|
|
}
|
|
|
|
// Process next address in the stack.
|
|
|
|
puiStack++;
|
|
}
|
|
*pszTmp = 0;
|
|
#ifdef FLM_WIN
|
|
if (pImgHlpSymbol)
|
|
{
|
|
os_free( pImgHlpSymbol);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#ifdef FLM_WIN
|
|
FLMINT iRet;
|
|
|
|
iRet = MessageBox( NULL, (LPCTSTR)szMessageBuffer, "WIN Memory Testing",
|
|
MB_ABORTRETRYIGNORE | MB_ICONINFORMATION | MB_TASKMODAL
|
|
| MB_SETFOREGROUND | MB_DEFBUTTON2);
|
|
if (iRet == IDIGNORE)
|
|
{
|
|
gv_FlmSysData.bLogLeaks = TRUE;
|
|
}
|
|
else if (iRet == IDABORT)
|
|
{
|
|
flmAssert( 0);
|
|
}
|
|
#else
|
|
gv_FlmSysData.bLogLeaks = TRUE;
|
|
#endif
|
|
|
|
if (gv_FlmSysData.bLogLeaks)
|
|
{
|
|
F_FileSystemImp FileSystem;
|
|
RCODE rc;
|
|
FLMUINT uiDummy;
|
|
#ifdef FLM_NLM
|
|
const char * pszErrPath = "sys:\\memtest.ert";
|
|
#else
|
|
const char * pszErrPath = "memtest.ert";
|
|
#endif
|
|
|
|
if (RC_BAD( rc = FileSystem.Open( pszErrPath,
|
|
F_IO_RDWR | F_IO_SH_DENYNONE, &pFileHdl)))
|
|
{
|
|
if (rc == FERR_IO_PATH_NOT_FOUND)
|
|
{
|
|
rc = FileSystem.Create( pszErrPath,
|
|
F_IO_RDWR | F_IO_SH_DENYNONE, &pFileHdl);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
FLMUINT uiOffset;
|
|
|
|
// Position to append to file.
|
|
|
|
rc = pFileHdl->Seek( 0, F_IO_SEEK_END, &uiOffset);
|
|
}
|
|
|
|
// If we successfully opened the file, write to it.
|
|
|
|
if (RC_OK( rc))
|
|
{
|
|
if (RC_OK( pFileHdl->Write( F_IO_CURRENT_POS,
|
|
(FLMUINT)(pszTmp - &szMessageBuffer [0]),
|
|
szMessageBuffer, &uiDummy)))
|
|
{
|
|
(void)pFileHdl->Flush();
|
|
}
|
|
pFileHdl->Close();
|
|
}
|
|
}
|
|
//Exit:
|
|
|
|
gv_FlmSysData.bTrackLeaks = bOldTrackLeaks;
|
|
|
|
if (pFileHdl)
|
|
{
|
|
pFileHdl->Release();
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/********************************************************************
|
|
Desc: Initialize memory - if not already done.
|
|
*********************************************************************/
|
|
void f_memoryInit( void)
|
|
{
|
|
#ifdef FLM_DEBUG
|
|
(void)initMemTracking();
|
|
#endif
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Clean up memory and check for unfreed memory.
|
|
*********************************************************************/
|
|
void f_memoryCleanup( void)
|
|
{
|
|
|
|
#ifdef FLM_DEBUG
|
|
if (initMemTracking())
|
|
{
|
|
FLMUINT uiId;
|
|
F_MEM_HDR * pHdr;
|
|
|
|
f_mutexLock( gv_FlmSysData.hMemTrackingMutex);
|
|
for (uiId = 0; uiId < gv_FlmSysData.uiMemTrackingPtrArraySize; uiId++)
|
|
{
|
|
if ((pHdr = (F_MEM_HDR *)gv_FlmSysData.ppvMemTrackingPtrs [uiId]) != NULL)
|
|
{
|
|
logMemLeak( pHdr);
|
|
freeMemTrackingInfo( TRUE, uiId + 1, pHdr->puiStack);
|
|
}
|
|
}
|
|
|
|
// Free the memory pointer array.
|
|
|
|
os_free( gv_FlmSysData.ppvMemTrackingPtrs);
|
|
gv_FlmSysData.ppvMemTrackingPtrs = NULL;
|
|
gv_FlmSysData.uiMemTrackingPtrArraySize = 0;
|
|
gv_FlmSysData.uiMemNumPtrs = 0;
|
|
|
|
f_mutexUnlock( gv_FlmSysData.hMemTrackingMutex);
|
|
|
|
// Free up the mutex.
|
|
|
|
f_mutexDestroy( &gv_FlmSysData.hMemTrackingMutex);
|
|
|
|
// Reset to unitialized state.
|
|
|
|
gv_FlmSysData.uiInitThreadId = 0;
|
|
gv_FlmSysData.hMemTrackingMutex = F_MUTEX_NULL;
|
|
gv_FlmSysData.bMemTrackingInitialized = FALSE;
|
|
#ifdef FLM_WIN
|
|
SymCleanup( gv_FlmSysData.hMemProcess);
|
|
#endif
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Allocate Memory.
|
|
*********************************************************************/
|
|
RCODE f_alloc(
|
|
FLMUINT uiSize,
|
|
void ** ppvPtr,
|
|
const char * pszFileName,
|
|
int iLineNumber)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
F_MEM_HDR * pHdr;
|
|
|
|
#ifndef FLM_DEBUG
|
|
F_UNREFERENCED_PARM( pszFileName);
|
|
F_UNREFERENCED_PARM( iLineNumber);
|
|
#endif
|
|
|
|
#ifdef DEBUG_SIM_OUT_OF_MEM
|
|
if ( SimulateOutOfMemory())
|
|
{
|
|
*ppvPtr = NULL;
|
|
rc = RC_SET( FERR_MEM);
|
|
goto Exit;
|
|
}
|
|
#endif
|
|
|
|
if ((pHdr = (F_MEM_HDR *)os_malloc( uiSize +
|
|
sizeof( F_MEM_HDR) +
|
|
F_PICKET_FENCE_SIZE)) == NULL)
|
|
{
|
|
rc = RC_SET( FERR_MEM);
|
|
goto Exit;
|
|
}
|
|
|
|
pHdr->uiDataSize = uiSize;
|
|
*ppvPtr = (void *)(&pHdr [1]);
|
|
|
|
#ifdef FLM_DEBUG
|
|
pHdr->iLineNumber = iLineNumber;
|
|
pHdr->pszFileName = pszFileName;
|
|
saveMemTrackingInfo( pHdr);
|
|
|
|
#if F_PICKET_FENCE_SIZE
|
|
|
|
f_memcpy( ((FLMBYTE *)(*ppvPtr)) + uiSize,
|
|
F_PICKET_FENCE, F_PICKET_FENCE_SIZE);
|
|
|
|
#endif
|
|
#endif
|
|
|
|
Exit:
|
|
|
|
return( rc);
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Allocate and initialize memory.
|
|
*********************************************************************/
|
|
RCODE f_calloc(
|
|
FLMUINT uiSize,
|
|
void ** ppvPtr,
|
|
const char * pszFileName,
|
|
int iLineNumber)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
F_MEM_HDR * pHdr;
|
|
|
|
#ifndef FLM_DEBUG
|
|
F_UNREFERENCED_PARM( pszFileName);
|
|
F_UNREFERENCED_PARM( iLineNumber);
|
|
#endif
|
|
|
|
#ifdef DEBUG_SIM_OUT_OF_MEM
|
|
if ( SimulateOutOfMemory())
|
|
{
|
|
*ppvPtr = NULL;
|
|
rc = RC_SET( FERR_MEM);
|
|
goto Exit;
|
|
}
|
|
#endif
|
|
|
|
if ((pHdr = (F_MEM_HDR *)os_malloc( uiSize +
|
|
sizeof( F_MEM_HDR) +
|
|
F_PICKET_FENCE_SIZE)) == NULL)
|
|
{
|
|
rc = RC_SET( FERR_MEM);
|
|
goto Exit;
|
|
}
|
|
|
|
pHdr->uiDataSize = uiSize;
|
|
*ppvPtr = (void *)(&pHdr [1]);
|
|
f_memset( *ppvPtr, 0, uiSize);
|
|
#ifdef FLM_DEBUG
|
|
pHdr->iLineNumber = iLineNumber;
|
|
pHdr->pszFileName = pszFileName;
|
|
saveMemTrackingInfo( pHdr);
|
|
|
|
#if F_PICKET_FENCE_SIZE
|
|
|
|
f_memcpy( ((FLMBYTE *)(*ppvPtr)) + uiSize,
|
|
F_PICKET_FENCE, F_PICKET_FENCE_SIZE);
|
|
|
|
#endif
|
|
|
|
#endif
|
|
Exit:
|
|
return( rc);
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Reallocate memory.
|
|
*********************************************************************/
|
|
RCODE f_realloc(
|
|
FLMUINT uiSize,
|
|
void ** ppvPtr,
|
|
const char * pszFileName,
|
|
int iLineNumber)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
F_MEM_HDR * pNewHdr;
|
|
#ifdef FLM_DEBUG
|
|
F_MEM_HDR * pOldHdr;
|
|
FLMUINT uiOldAllocationId;
|
|
FLMUINT * puiOldStack;
|
|
#endif
|
|
|
|
#ifdef DEBUG_SIM_OUT_OF_MEM
|
|
if ( SimulateOutOfMemory())
|
|
{
|
|
*ppvPtr = NULL;
|
|
rc = RC_SET( FERR_MEM);
|
|
goto Exit;
|
|
}
|
|
#endif
|
|
|
|
if (!(*ppvPtr))
|
|
{
|
|
rc = f_alloc( uiSize, ppvPtr, pszFileName, iLineNumber);
|
|
goto Exit;
|
|
}
|
|
|
|
#ifdef FLM_DEBUG
|
|
pOldHdr = (F_MEM_HDR *)F_GET_ALLOC_PTR( *ppvPtr);
|
|
|
|
#if F_PICKET_FENCE_SIZE
|
|
|
|
// Verify the old picket fence
|
|
|
|
if (f_memcmp( ((FLMBYTE *)(*ppvPtr)) + pOldHdr->uiDataSize,
|
|
F_PICKET_FENCE, F_PICKET_FENCE_SIZE) != 0)
|
|
{
|
|
flmAssert( 0);
|
|
}
|
|
|
|
#endif
|
|
|
|
uiOldAllocationId = pOldHdr->uiAllocationId;
|
|
puiOldStack = pOldHdr->puiStack;
|
|
#endif
|
|
|
|
if ((pNewHdr = (F_MEM_HDR *)os_realloc( F_GET_ALLOC_PTR( *ppvPtr),
|
|
uiSize + sizeof( F_MEM_HDR) +
|
|
F_PICKET_FENCE_SIZE)) == NULL)
|
|
{
|
|
rc = RC_SET( FERR_MEM);
|
|
goto Exit;
|
|
}
|
|
|
|
pNewHdr->uiDataSize = uiSize;
|
|
*ppvPtr = (void *)(&pNewHdr [1]);
|
|
#ifdef FLM_DEBUG
|
|
pNewHdr->iLineNumber = iLineNumber;
|
|
pNewHdr->pszFileName = pszFileName;
|
|
if (pNewHdr != pOldHdr)
|
|
{
|
|
freeMemTrackingInfo( FALSE, uiOldAllocationId, puiOldStack);
|
|
saveMemTrackingInfo( pNewHdr);
|
|
}
|
|
else
|
|
{
|
|
updateMemTrackingInfo( pNewHdr);
|
|
}
|
|
|
|
#if F_PICKET_FENCE_SIZE
|
|
|
|
f_memcpy( ((FLMBYTE *)(*ppvPtr)) + uiSize,
|
|
F_PICKET_FENCE, F_PICKET_FENCE_SIZE);
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
Exit:
|
|
return( rc);
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Reallocate memory, and initialize the new part.
|
|
*********************************************************************/
|
|
RCODE f_recalloc(
|
|
FLMUINT uiSize,
|
|
void ** ppvPtr,
|
|
const char * pszFileName,
|
|
int iLineNumber)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
F_MEM_HDR * pNewHdr;
|
|
FLMUINT uiOldSize;
|
|
#ifdef FLM_DEBUG
|
|
F_MEM_HDR * pOldHdr;
|
|
FLMUINT uiOldAllocationId;
|
|
FLMUINT * puiOldStack;
|
|
#endif
|
|
|
|
#ifdef DEBUG_SIM_OUT_OF_MEM
|
|
if ( SimulateOutOfMemory())
|
|
{
|
|
*ppvPtr = NULL;
|
|
rc = RC_SET( FERR_MEM);
|
|
goto Exit;
|
|
}
|
|
#endif
|
|
|
|
if (!(*ppvPtr))
|
|
{
|
|
rc = f_calloc( uiSize, ppvPtr, pszFileName, iLineNumber);
|
|
goto Exit;
|
|
}
|
|
|
|
#ifdef FLM_DEBUG
|
|
pOldHdr = (F_MEM_HDR *)F_GET_ALLOC_PTR( *ppvPtr);
|
|
|
|
#if F_PICKET_FENCE_SIZE
|
|
|
|
// Verify the old picket fence
|
|
|
|
if (f_memcmp( ((FLMBYTE *)(*ppvPtr)) + pOldHdr->uiDataSize,
|
|
F_PICKET_FENCE, F_PICKET_FENCE_SIZE) != 0)
|
|
{
|
|
flmAssert( 0);
|
|
}
|
|
|
|
#endif
|
|
|
|
uiOldAllocationId = pOldHdr->uiAllocationId;
|
|
puiOldStack = pOldHdr->puiStack;
|
|
|
|
#endif
|
|
|
|
uiOldSize = F_GET_MEM_DATA_SIZE( *ppvPtr);
|
|
|
|
if ((pNewHdr = (F_MEM_HDR *)os_realloc( F_GET_ALLOC_PTR( *ppvPtr),
|
|
uiSize + sizeof( F_MEM_HDR) +
|
|
F_PICKET_FENCE_SIZE)) == NULL)
|
|
{
|
|
rc = RC_SET( FERR_MEM);
|
|
goto Exit;
|
|
}
|
|
|
|
pNewHdr->uiDataSize = uiSize;
|
|
*ppvPtr = (void *)(&pNewHdr [1]);
|
|
if (uiOldSize < uiSize)
|
|
{
|
|
f_memset( ((FLMBYTE *)(*ppvPtr)) + uiOldSize, 0,
|
|
uiSize - uiOldSize);
|
|
}
|
|
#ifdef FLM_DEBUG
|
|
pNewHdr->iLineNumber = iLineNumber;
|
|
pNewHdr->pszFileName = pszFileName;
|
|
if (pNewHdr != pOldHdr)
|
|
{
|
|
freeMemTrackingInfo( FALSE, uiOldAllocationId, puiOldStack);
|
|
saveMemTrackingInfo( pNewHdr);
|
|
}
|
|
else
|
|
{
|
|
updateMemTrackingInfo( pNewHdr);
|
|
}
|
|
|
|
#if F_PICKET_FENCE_SIZE
|
|
|
|
f_memcpy( ((FLMBYTE *)(*ppvPtr)) + uiSize,
|
|
F_PICKET_FENCE, F_PICKET_FENCE_SIZE);
|
|
|
|
#endif
|
|
|
|
#endif
|
|
Exit:
|
|
return( rc);
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Free previously allocated memory.
|
|
*********************************************************************/
|
|
void f_free(
|
|
void ** ppvPtr)
|
|
{
|
|
if (*ppvPtr)
|
|
{
|
|
|
|
#ifdef FLM_DEBUG
|
|
F_MEM_HDR * pHdr = (F_MEM_HDR *)F_GET_ALLOC_PTR( *ppvPtr);
|
|
|
|
#if F_PICKET_FENCE_SIZE
|
|
|
|
// Check the picket fence
|
|
|
|
if (f_memcmp( ((FLMBYTE *)(*ppvPtr)) + pHdr->uiDataSize,
|
|
F_PICKET_FENCE, F_PICKET_FENCE_SIZE) != 0)
|
|
{
|
|
flmAssert( 0);
|
|
}
|
|
|
|
#endif
|
|
|
|
freeMemTrackingInfo( FALSE, pHdr->uiAllocationId, pHdr->puiStack);
|
|
#endif
|
|
|
|
os_free( F_GET_ALLOC_PTR( *ppvPtr));
|
|
*ppvPtr = NULL;
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
#ifdef FLM_NLM
|
|
void * nlm_realloc(
|
|
void * pMemory,
|
|
size_t newSize)
|
|
{
|
|
void * pNewMemory;
|
|
LONG lSize;
|
|
|
|
if( !pMemory)
|
|
{
|
|
pNewMemory = Alloc( newSize, gv_lAllocRTag);
|
|
goto Exit;
|
|
}
|
|
|
|
lSize = SizeOfAllocBlock( pMemory);
|
|
|
|
pNewMemory = os_malloc( newSize);
|
|
if( !pNewMemory)
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if( lSize > newSize)
|
|
{
|
|
lSize = newSize;
|
|
}
|
|
|
|
f_memcpy( pNewMemory, pMemory, lSize);
|
|
|
|
if( pMemory)
|
|
{
|
|
Free( pMemory);
|
|
}
|
|
|
|
Exit:
|
|
|
|
return( pNewMemory);
|
|
}
|
|
#endif
|
|
|
|
#undef new
|
|
#undef delete
|
|
#define FLM_NEW_MEMORY_SIGNATURE 0xABCDABCD
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
void * F_Base::operator new(
|
|
FLMSIZET uiSize)
|
|
#ifndef FLM_NLM
|
|
throw()
|
|
#endif
|
|
{
|
|
void * pvReturnPtr = NULL;
|
|
|
|
uiSize += FLM_ALIGN_SIZE;
|
|
f_alloc( uiSize, &pvReturnPtr, "unknown", 0);
|
|
|
|
if( pvReturnPtr)
|
|
{
|
|
*((FLMUINT *)pvReturnPtr) = FLM_NEW_MEMORY_SIGNATURE;
|
|
pvReturnPtr = (void *)(((FLMBYTE *)pvReturnPtr) + FLM_ALIGN_SIZE);
|
|
}
|
|
|
|
return( pvReturnPtr);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
void * F_Base::operator new[](
|
|
FLMSIZET uiSize)
|
|
#ifndef FLM_NLM
|
|
throw()
|
|
#endif
|
|
{
|
|
void * pvReturnPtr = NULL;
|
|
|
|
uiSize += FLM_ALIGN_SIZE;
|
|
f_alloc( uiSize, &pvReturnPtr, "unknown", 0);
|
|
|
|
if( pvReturnPtr)
|
|
{
|
|
*((FLMUINT *)pvReturnPtr) = FLM_NEW_MEMORY_SIGNATURE;
|
|
pvReturnPtr = (void *)(((FLMBYTE *)pvReturnPtr) + FLM_ALIGN_SIZE);
|
|
}
|
|
|
|
return( pvReturnPtr);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
#ifdef FLM_DEBUG
|
|
void * F_Base::operator new(
|
|
FLMSIZET uiSize,
|
|
const char * pszFile,
|
|
int iLine)
|
|
#ifndef FLM_NLM
|
|
throw()
|
|
#endif
|
|
{
|
|
void * pvReturnPtr = NULL;
|
|
|
|
uiSize += FLM_ALIGN_SIZE;
|
|
f_alloc( uiSize, &pvReturnPtr, pszFile, iLine);
|
|
|
|
if( pvReturnPtr)
|
|
{
|
|
*((FLMUINT *)pvReturnPtr) = FLM_NEW_MEMORY_SIGNATURE;
|
|
pvReturnPtr = (void *)(((FLMBYTE *)pvReturnPtr) + FLM_ALIGN_SIZE);
|
|
}
|
|
|
|
return( pvReturnPtr);
|
|
}
|
|
#endif
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
#ifdef FLM_DEBUG
|
|
void * F_Base::operator new[](
|
|
FLMSIZET uiSize,
|
|
const char * pszFile,
|
|
int iLine)
|
|
#ifndef FLM_NLM
|
|
throw()
|
|
#endif
|
|
{
|
|
void * pvReturnPtr = NULL;
|
|
|
|
uiSize += FLM_ALIGN_SIZE;
|
|
f_alloc( uiSize, &pvReturnPtr, pszFile, iLine);
|
|
|
|
if( pvReturnPtr)
|
|
{
|
|
*((FLMUINT *)pvReturnPtr) = FLM_NEW_MEMORY_SIGNATURE;
|
|
pvReturnPtr = (void *)(((FLMBYTE *)pvReturnPtr) + FLM_ALIGN_SIZE);
|
|
}
|
|
|
|
return( pvReturnPtr);
|
|
}
|
|
#endif
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
void F_Base::operator delete(
|
|
void * ptr)
|
|
{
|
|
if( !ptr)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ptr = (void *)(((FLMBYTE *)ptr) - FLM_ALIGN_SIZE);
|
|
if( *((FLMUINT *)ptr) != FLM_NEW_MEMORY_SIGNATURE)
|
|
{
|
|
// Something is wrong with the allocation ... don't
|
|
// try to free it.
|
|
|
|
flmAssert( 0);
|
|
return;
|
|
}
|
|
|
|
f_free( &ptr);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
void F_Base::operator delete[](
|
|
void * ptr)
|
|
{
|
|
if( !ptr)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ptr = (void *)(((FLMBYTE *)ptr) - FLM_ALIGN_SIZE);
|
|
if( *((FLMUINT *)ptr) != FLM_NEW_MEMORY_SIGNATURE)
|
|
{
|
|
// Something is wrong with the allocation ... don't
|
|
// try to free it.
|
|
|
|
flmAssert( 0);
|
|
return;
|
|
}
|
|
|
|
f_free( &ptr);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
#if defined( FLM_DEBUG) && !defined( __WATCOMC__)
|
|
void F_Base::operator delete(
|
|
void * ptr,
|
|
const char *, // file
|
|
int) // line
|
|
{
|
|
if( !ptr)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ptr = (void *)(((FLMBYTE *)ptr) - FLM_ALIGN_SIZE);
|
|
if( *((FLMUINT *)ptr) != FLM_NEW_MEMORY_SIGNATURE)
|
|
{
|
|
// Something is wrong with the allocation ... don't
|
|
// try to free it.
|
|
|
|
flmAssert( 0);
|
|
return;
|
|
}
|
|
|
|
f_free( &ptr);
|
|
}
|
|
#endif
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
#if defined( FLM_DEBUG) && !defined( __WATCOMC__)
|
|
void F_Base::operator delete[](
|
|
void * ptr,
|
|
const char *, // file
|
|
int // line
|
|
)
|
|
{
|
|
if( !ptr)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ptr = (void *)(((FLMBYTE *)ptr) - FLM_ALIGN_SIZE);
|
|
if( *((FLMUINT *)ptr) != FLM_NEW_MEMORY_SIGNATURE)
|
|
{
|
|
// Something is wrong with the allocation ... don't
|
|
// try to free it.
|
|
|
|
flmAssert( 0);
|
|
return;
|
|
}
|
|
|
|
f_free( &ptr);
|
|
}
|
|
#endif
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
FLMINT F_Base::Release( void)
|
|
{
|
|
FLMINT iRefCnt = --m_refCnt;
|
|
|
|
if( !iRefCnt)
|
|
{
|
|
delete this;
|
|
}
|
|
|
|
return( iRefCnt);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
FLMEXP void FLMAPI FlmFreeMem(
|
|
void * pMem)
|
|
{
|
|
f_free( &pMem);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
FLMUINT f_msize(
|
|
void * pvPtr)
|
|
{
|
|
#if defined( FLM_UNIX)
|
|
return( pvPtr ? F_GET_MEM_DATA_SIZE( (pvPtr)) : 0);
|
|
#elif defined( FLM_NLM)
|
|
return( pvPtr ? (unsigned)SizeOfAllocBlock(
|
|
(F_GET_ALLOC_PTR( (pvPtr)))) : 0);
|
|
#else
|
|
return( pvPtr ? _msize( (F_GET_ALLOC_PTR( (pvPtr)))) : 0);
|
|
#endif
|
|
}
|