1 // Copyright (C) 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 ******************************************************************************
6 * Copyright (C) 2002-2015, International Business Machines
7 * Corporation and others. All Rights Reserved.
9 ******************************************************************************
11 * File cmemory.c ICU Heap allocation.
12 * All ICU heap allocation, both for C and C++ new of ICU
13 * class types, comes through these functions.
15 * If you have a need to replace ICU allocation, this is the
18 * Note that uprv_malloc(0) returns a non-NULL pointer, and
19 * that a subsequent free of that pointer value is a NOP.
21 ******************************************************************************
23 #include "unicode/uclean.h"
29 /* uprv_malloc(0) returns a pointer to this read-only data. */
30 static const int32_t zeroMem[] = {0, 0, 0, 0, 0, 0};
32 /* Function Pointers for user-supplied heap functions */
33 static const void *pContext;
34 static UMemAllocFn *pAlloc;
35 static UMemReallocFn *pRealloc;
36 static UMemFreeFn *pFree;
38 #if U_DEBUG && defined(UPRV_MALLOC_COUNT)
46 static char gValidMemorySink = 0;
48 U_CAPI void uprv_checkValidMemory(const void *p, size_t n) {
50 * Access the memory to ensure that it's all valid.
51 * Load and save a computed value to try to ensure that the compiler
52 * does not throw away the whole loop.
53 * A thread analyzer might complain about un-mutexed access to gValidMemorySink
54 * which is true but harmless because no one ever uses the value in gValidMemorySink.
56 const char *s = (const char *)p;
57 char c = gValidMemorySink;
60 for(i = 0; i < n; ++i) {
68 U_CAPI void * U_EXPORT2
69 uprv_malloc(size_t s) {
70 #if U_DEBUG && defined(UPRV_MALLOC_COUNT)
75 fprintf(stderr,"MALLOC\t#%d\t%ul bytes\t%ul total\n", ++n,s,(b+=s)); fflush(stderr);
80 return (*pAlloc)(pContext, s);
82 return uprv_default_malloc(s);
85 return (void *)zeroMem;
89 U_CAPI void * U_EXPORT2
90 uprv_realloc(void * buffer, size_t size) {
91 #if U_DEBUG && defined(UPRV_MALLOC_COUNT)
95 if (buffer == zeroMem) {
96 return uprv_malloc(size);
97 } else if (size == 0) {
99 (*pFree)(pContext, buffer);
101 uprv_default_free(buffer);
103 return (void *)zeroMem;
106 return (*pRealloc)(pContext, buffer, size);
108 return uprv_default_realloc(buffer, size);
113 U_CAPI void U_EXPORT2
114 uprv_free(void *buffer) {
115 #if U_DEBUG && defined(UPRV_MALLOC_COUNT)
119 if (buffer != zeroMem) {
121 (*pFree)(pContext, buffer);
123 uprv_default_free(buffer);
128 U_CAPI void * U_EXPORT2
129 uprv_calloc(size_t num, size_t size) {
132 mem = uprv_malloc(size);
134 uprv_memset(mem, 0, size);
139 U_CAPI void U_EXPORT2
140 u_setMemoryFunctions(const void *context, UMemAllocFn *a, UMemReallocFn *r, UMemFreeFn *f, UErrorCode *status)
142 if (U_FAILURE(*status)) {
145 if (a==NULL || r==NULL || f==NULL) {
146 *status = U_ILLEGAL_ARGUMENT_ERROR;
156 U_CFUNC UBool cmemory_cleanup(void) {