2002-07-29 21:29:23 +00:00
|
|
|
/*
|
|
|
|
******************************************************************************
|
|
|
|
*
|
2015-02-27 23:01:33 +00:00
|
|
|
* Copyright (C) 2002-2015, International Business Machines
|
2002-07-29 21:29:23 +00:00
|
|
|
* Corporation and others. All Rights Reserved.
|
|
|
|
*
|
|
|
|
******************************************************************************
|
|
|
|
*
|
2002-07-29 22:15:14 +00:00
|
|
|
* File cmemory.c ICU Heap allocation.
|
|
|
|
* All ICU heap allocation, both for C and C++ new of ICU
|
|
|
|
* class types, comes through these functions.
|
|
|
|
*
|
|
|
|
* If you have a need to replace ICU allocation, this is the
|
|
|
|
* place to do it.
|
|
|
|
*
|
|
|
|
* Note that uprv_malloc(0) returns a non-NULL pointer, and
|
|
|
|
* that a subsequent free of that pointer value is a NOP.
|
2002-07-29 21:29:23 +00:00
|
|
|
*
|
|
|
|
******************************************************************************
|
|
|
|
*/
|
2003-08-05 01:25:54 +00:00
|
|
|
#include "unicode/uclean.h"
|
2004-12-03 20:22:01 +00:00
|
|
|
#include "cmemory.h"
|
2011-09-15 19:34:17 +00:00
|
|
|
#include "putilimp.h"
|
2012-06-07 00:14:54 +00:00
|
|
|
#include "uassert.h"
|
2004-12-03 20:22:01 +00:00
|
|
|
#include <stdlib.h>
|
2002-07-29 21:29:23 +00:00
|
|
|
|
2012-06-07 00:14:54 +00:00
|
|
|
/* uprv_malloc(0) returns a pointer to this read-only data. */
|
2002-07-29 22:15:14 +00:00
|
|
|
static const int32_t zeroMem[] = {0, 0, 0, 0, 0, 0};
|
|
|
|
|
2003-08-05 01:25:54 +00:00
|
|
|
/* Function Pointers for user-supplied heap functions */
|
2003-08-14 21:34:54 +00:00
|
|
|
static const void *pContext;
|
|
|
|
static UMemAllocFn *pAlloc;
|
|
|
|
static UMemReallocFn *pRealloc;
|
|
|
|
static UMemFreeFn *pFree;
|
2003-08-05 01:25:54 +00:00
|
|
|
|
2012-05-30 00:41:57 +00:00
|
|
|
#if U_DEBUG && defined(UPRV_MALLOC_COUNT)
|
|
|
|
#include <stdio.h>
|
|
|
|
static int n=0;
|
|
|
|
static long b=0;
|
|
|
|
#endif
|
|
|
|
|
2012-06-07 00:14:54 +00:00
|
|
|
#if U_DEBUG
|
|
|
|
|
|
|
|
static char gValidMemorySink = 0;
|
|
|
|
|
|
|
|
U_CAPI void uprv_checkValidMemory(const void *p, size_t n) {
|
|
|
|
/*
|
|
|
|
* Access the memory to ensure that it's all valid.
|
|
|
|
* Load and save a computed value to try to ensure that the compiler
|
|
|
|
* does not throw away the whole loop.
|
|
|
|
* A thread analyzer might complain about un-mutexed access to gValidMemorySink
|
|
|
|
* which is true but harmless because no one ever uses the value in gValidMemorySink.
|
|
|
|
*/
|
|
|
|
const char *s = (const char *)p;
|
|
|
|
char c = gValidMemorySink;
|
|
|
|
size_t i;
|
|
|
|
U_ASSERT(p != NULL);
|
|
|
|
for(i = 0; i < n; ++i) {
|
|
|
|
c ^= s[i];
|
|
|
|
}
|
|
|
|
gValidMemorySink = c;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* U_DEBUG */
|
2012-05-30 00:41:57 +00:00
|
|
|
|
2002-07-29 21:29:23 +00:00
|
|
|
U_CAPI void * U_EXPORT2
|
|
|
|
uprv_malloc(size_t s) {
|
2012-05-30 00:41:57 +00:00
|
|
|
#if U_DEBUG && defined(UPRV_MALLOC_COUNT)
|
|
|
|
#if 1
|
|
|
|
putchar('>');
|
|
|
|
fflush(stdout);
|
|
|
|
#else
|
|
|
|
fprintf(stderr,"MALLOC\t#%d\t%ul bytes\t%ul total\n", ++n,s,(b+=s)); fflush(stderr);
|
|
|
|
#endif
|
|
|
|
#endif
|
2002-07-29 22:15:14 +00:00
|
|
|
if (s > 0) {
|
2003-08-05 01:25:54 +00:00
|
|
|
if (pAlloc) {
|
|
|
|
return (*pAlloc)(pContext, s);
|
|
|
|
} else {
|
2011-09-15 19:34:17 +00:00
|
|
|
return uprv_default_malloc(s);
|
2003-08-05 01:25:54 +00:00
|
|
|
}
|
2002-07-29 22:15:14 +00:00
|
|
|
} else {
|
|
|
|
return (void *)zeroMem;
|
|
|
|
}
|
2002-07-29 21:29:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
U_CAPI void * U_EXPORT2
|
|
|
|
uprv_realloc(void * buffer, size_t size) {
|
2012-05-30 00:41:57 +00:00
|
|
|
#if U_DEBUG && defined(UPRV_MALLOC_COUNT)
|
|
|
|
putchar('~');
|
|
|
|
fflush(stdout);
|
|
|
|
#endif
|
2002-08-07 21:34:31 +00:00
|
|
|
if (buffer == zeroMem) {
|
2002-07-29 22:15:14 +00:00
|
|
|
return uprv_malloc(size);
|
2002-08-07 21:34:31 +00:00
|
|
|
} else if (size == 0) {
|
2003-08-05 01:25:54 +00:00
|
|
|
if (pFree) {
|
|
|
|
(*pFree)(pContext, buffer);
|
|
|
|
} else {
|
2011-09-15 19:34:17 +00:00
|
|
|
uprv_default_free(buffer);
|
2003-08-05 01:25:54 +00:00
|
|
|
}
|
2002-08-07 21:34:31 +00:00
|
|
|
return (void *)zeroMem;
|
2002-07-29 22:15:14 +00:00
|
|
|
} else {
|
2003-08-05 01:25:54 +00:00
|
|
|
if (pRealloc) {
|
|
|
|
return (*pRealloc)(pContext, buffer, size);
|
|
|
|
} else {
|
2011-09-15 19:34:17 +00:00
|
|
|
return uprv_default_realloc(buffer, size);
|
2003-08-05 01:25:54 +00:00
|
|
|
}
|
2002-07-29 22:15:14 +00:00
|
|
|
}
|
2002-07-29 21:29:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
U_CAPI void U_EXPORT2
|
|
|
|
uprv_free(void *buffer) {
|
2012-05-30 00:41:57 +00:00
|
|
|
#if U_DEBUG && defined(UPRV_MALLOC_COUNT)
|
|
|
|
putchar('<');
|
|
|
|
fflush(stdout);
|
|
|
|
#endif
|
2002-07-29 22:15:14 +00:00
|
|
|
if (buffer != zeroMem) {
|
2003-08-05 01:25:54 +00:00
|
|
|
if (pFree) {
|
|
|
|
(*pFree)(pContext, buffer);
|
|
|
|
} else {
|
2011-09-15 19:34:17 +00:00
|
|
|
uprv_default_free(buffer);
|
2003-08-05 01:25:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-30 17:52:02 +00:00
|
|
|
U_CAPI void * U_EXPORT2
|
|
|
|
uprv_calloc(size_t num, size_t size) {
|
2011-12-02 04:40:30 +00:00
|
|
|
void *mem = NULL;
|
2011-11-30 17:52:02 +00:00
|
|
|
size *= num;
|
2011-12-02 04:40:30 +00:00
|
|
|
mem = uprv_malloc(size);
|
2011-11-30 17:52:02 +00:00
|
|
|
if (mem) {
|
|
|
|
uprv_memset(mem, 0, size);
|
|
|
|
}
|
|
|
|
return mem;
|
|
|
|
}
|
|
|
|
|
2003-08-05 01:25:54 +00:00
|
|
|
U_CAPI void U_EXPORT2
|
2003-08-14 21:34:54 +00:00
|
|
|
u_setMemoryFunctions(const void *context, UMemAllocFn *a, UMemReallocFn *r, UMemFreeFn *f, UErrorCode *status)
|
2003-08-05 01:25:54 +00:00
|
|
|
{
|
|
|
|
if (U_FAILURE(*status)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (a==NULL || r==NULL || f==NULL) {
|
|
|
|
*status = U_ILLEGAL_ARGUMENT_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
pContext = context;
|
|
|
|
pAlloc = a;
|
|
|
|
pRealloc = r;
|
|
|
|
pFree = f;
|
2002-07-29 21:29:23 +00:00
|
|
|
}
|
|
|
|
|
2003-08-05 01:25:54 +00:00
|
|
|
|
|
|
|
U_CFUNC UBool cmemory_cleanup(void) {
|
|
|
|
pContext = NULL;
|
|
|
|
pAlloc = NULL;
|
|
|
|
pRealloc = NULL;
|
|
|
|
pFree = NULL;
|
|
|
|
return TRUE;
|
|
|
|
}
|