261 lines
7.0 KiB
C
261 lines
7.0 KiB
C
/*************************************************************************/
|
|
/* */
|
|
/* Language Technologies Institute */
|
|
/* Carnegie Mellon University */
|
|
/* Copyright (c) 1999 */
|
|
/* All Rights Reserved. */
|
|
/* */
|
|
/* Permission is hereby granted, free of charge, to use and distribute */
|
|
/* this software and its documentation without restriction, including */
|
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
|
/* distribute, sublicense, and/or sell copies of this work, and to */
|
|
/* permit persons to whom this work is furnished to do so, subject to */
|
|
/* the following conditions: */
|
|
/* 1. The code must retain the above copyright notice, this list of */
|
|
/* conditions and the following disclaimer. */
|
|
/* 2. Any modifications must be clearly marked as such. */
|
|
/* 3. Original authors' names are not deleted. */
|
|
/* 4. The authors' names are not used to endorse or promote products */
|
|
/* derived from this software without specific prior written */
|
|
/* permission. */
|
|
/* */
|
|
/* CARNEGIE MELLON UNIVERSITY AND THE CONTRIBUTORS TO THIS WORK */
|
|
/* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */
|
|
/* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */
|
|
/* SHALL CARNEGIE MELLON UNIVERSITY NOR THE CONTRIBUTORS BE LIABLE */
|
|
/* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */
|
|
/* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */
|
|
/* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */
|
|
/* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */
|
|
/* THIS SOFTWARE. */
|
|
/* */
|
|
/*************************************************************************/
|
|
/* Author: Alan W Black (awb@cs.cmu.edu) */
|
|
/* Date: July 1999 */
|
|
/*************************************************************************/
|
|
/* */
|
|
/* Basic wraparounds for malloc and free */
|
|
/* */
|
|
/*************************************************************************/
|
|
#include "cst_file.h"
|
|
#include "cst_alloc.h"
|
|
#include "cst_error.h"
|
|
|
|
#ifdef UNDER_CE
|
|
#include <windows.h>
|
|
#endif /* UNDER_CE */
|
|
|
|
/* define this if you want to trace memory usage */
|
|
/* #define CST_DEBUG_MALLOC */
|
|
/* #define CST_DEBUG_MALLOC_TRACE */
|
|
#ifdef CST_DEBUG_MALLOC
|
|
int cst_allocated = 0;
|
|
int cst_freed = 0;
|
|
int cst_alloc_max = 0;
|
|
int cst_alloc_imax = 0;
|
|
int cst_alloc_num_calls = 0;
|
|
int cst_alloc_out = 0;
|
|
#ifdef CST_DEBUG_MALLOC_TRACE
|
|
/* This is a crude memory tracer to find leaks */
|
|
int cst_alloc_ckpt = -1;
|
|
/* You have to know how big this should be to use it, its for debuging only */
|
|
#define NUM_CHUNKS 10000000
|
|
void *cst_alloc_cunks[NUM_CHUNKS];
|
|
#endif
|
|
#endif
|
|
|
|
void *cst_safe_alloc(int size)
|
|
{
|
|
/* returns pointer to memory all set 0 */
|
|
void *p = NULL;
|
|
if (size < 0)
|
|
{
|
|
cst_errmsg("alloc: asked for negative size %d\n", size);
|
|
cst_error();
|
|
}
|
|
else if (size == 0) /* some mallocs return NULL for this */
|
|
size++;
|
|
|
|
#ifdef CST_DEBUG_MALLOC
|
|
if (size > cst_alloc_imax)
|
|
{
|
|
cst_alloc_imax = size;
|
|
}
|
|
cst_allocated += size;
|
|
cst_alloc_out += size;
|
|
size += 2 * sizeof(int);
|
|
#endif
|
|
|
|
#ifdef UNDER_CE
|
|
p = (void *)LocalAlloc(LPTR, size);
|
|
#else
|
|
p = (void *)calloc(size,1);
|
|
#endif
|
|
|
|
#ifdef CST_DEBUG_MALLOC
|
|
#ifdef CST_DEBUG_MALLOC_TRACE
|
|
if (cst_alloc_num_calls == cst_alloc_ckpt)
|
|
cst_dbgmsg("cst_malloc: %d\n", cst_alloc_ckpt);
|
|
cst_alloc_cunks[cst_alloc_num_calls] = p;
|
|
#endif
|
|
cst_alloc_num_calls++;
|
|
*(int *)p = 1314;
|
|
p = (int *)p + 1;
|
|
*(int *)p = size - (2 * sizeof(int));
|
|
if ((cst_allocated - cst_freed) > cst_alloc_max)
|
|
cst_alloc_max = cst_allocated - cst_freed;
|
|
p = (int *)p + 1;
|
|
#endif
|
|
|
|
if (p == NULL)
|
|
{
|
|
cst_errmsg("alloc: can't alloc %d bytes\n", size);
|
|
cst_error();
|
|
}
|
|
|
|
return p;
|
|
}
|
|
|
|
void *cst_safe_calloc(int size)
|
|
{
|
|
return cst_safe_alloc(size);
|
|
}
|
|
|
|
void *cst_safe_realloc(void *p,int size)
|
|
{
|
|
void *np=0;
|
|
|
|
#ifdef CST_DEBUG_MALLOC
|
|
cst_free(p);
|
|
return cst_safe_alloc(size);
|
|
#endif
|
|
|
|
if (size == 0)
|
|
size++; /* as some mallocs do strange things with 0 */
|
|
|
|
if (p == NULL)
|
|
np = cst_safe_alloc(size);
|
|
else
|
|
#ifdef UNDER_CE
|
|
np = LocalReAlloc((HLOCAL)p, size, LMEM_MOVEABLE|LMEM_ZEROINIT);
|
|
#else
|
|
np = realloc(p,size);
|
|
#endif
|
|
|
|
if (np == NULL)
|
|
{
|
|
cst_errmsg("CST_REALLOC failed for %d bytes\n",size);
|
|
cst_error();
|
|
}
|
|
|
|
return np;
|
|
}
|
|
|
|
void cst_free(void *p)
|
|
{
|
|
if (p != NULL)
|
|
{
|
|
#ifdef CST_DEBUG_MALLOC
|
|
if (*((int *)p - 2) != 1314)
|
|
{
|
|
cst_dbgmsg("CST_MALLOC_DEBUG freeing non-malloc memory\n");
|
|
return;
|
|
}
|
|
if (*((int *)p - 1) <= 0)
|
|
{
|
|
cst_dbgmsg("CST_MALLOC_DEBUG re-freeing memory\n");
|
|
return;
|
|
}
|
|
cst_freed += *((int *)p - 1);
|
|
cst_alloc_out -= *((int *)p - 1);
|
|
*((int *)p - 1) = 0; /* mark it as freed */
|
|
p = (int *)p - 2;
|
|
#endif
|
|
#ifndef CST_DEBUG_MALLOC_TRACE
|
|
#ifdef UNDER_CE
|
|
if (LocalFree(p) != NULL)
|
|
{
|
|
cst_errmsg("LocalFree(%p) failed with code %x\n",
|
|
p, GetLastError());
|
|
cst_error();
|
|
}
|
|
#else
|
|
free(p);
|
|
#endif
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#ifdef CST_DEBUG_MALLOC_TRACE
|
|
|
|
void cst_find_unfreed()
|
|
{
|
|
int i, t;
|
|
|
|
|
|
for (i = 0, t = 0;
|
|
i < NUM_CHUNKS
|
|
&& i < cst_alloc_num_calls
|
|
&& cst_alloc_cunks[i];
|
|
i++)
|
|
{
|
|
if (((int *)cst_alloc_cunks[i])[1] != 0)
|
|
{
|
|
cst_dbgmsg("unfreed at %d\n", i);
|
|
t++;
|
|
}
|
|
}
|
|
cst_dbgmsg("total unfreed %d\n", t);
|
|
}
|
|
|
|
void cst_alloc_debug_summary()
|
|
{
|
|
cst_find_unfreed();
|
|
printf("allocated %d freed %d max %d imax %d calls %d out %d\n",
|
|
cst_allocated, cst_freed, cst_alloc_max,
|
|
cst_alloc_imax, cst_alloc_num_calls, cst_alloc_out);
|
|
}
|
|
#endif
|
|
|
|
#ifdef UNDER_CE
|
|
cst_alloc_context new_alloc_context(int size)
|
|
{
|
|
HANDLE h;
|
|
|
|
h = HeapCreate(0, size, 0);
|
|
return (cst_alloc_context) h;
|
|
}
|
|
|
|
void delete_alloc_context(cst_alloc_context ctx)
|
|
{
|
|
HANDLE h;
|
|
|
|
h = (HANDLE)ctx;
|
|
HeapDestroy(h);
|
|
}
|
|
|
|
void *cst_local_alloc(cst_alloc_context ctx, int size)
|
|
{
|
|
HANDLE h;
|
|
|
|
h = (HANDLE)ctx;
|
|
if (h)
|
|
return HeapAlloc(h, HEAP_ZERO_MEMORY, size);
|
|
else
|
|
return LocalAlloc(LPTR, size);
|
|
}
|
|
|
|
void cst_local_free(cst_alloc_context ctx, void *p)
|
|
{
|
|
HANDLE h;
|
|
|
|
h = (HANDLE)ctx;
|
|
if (h)
|
|
HeapFree(h, 0, p);
|
|
else
|
|
LocalFree(p);
|
|
}
|
|
#endif
|
|
|
|
|