1 // Copyright (C) 2016 and later: Unicode, Inc. and others. 2 // License & terms of use: http://www.unicode.org/copyright.html 3 /* 4 ****************************************************************************** 5 * 6 * Copyright (C) 2002-2015, International Business Machines 7 * Corporation and others. All Rights Reserved. 8 * 9 ****************************************************************************** 10 * 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. 14 * 15 * If you have a need to replace ICU allocation, this is the 16 * place to do it. 17 * 18 * Note that uprv_malloc(0) returns a non-NULL pointer, and 19 * that a subsequent free of that pointer value is a NOP. 20 * 21 ****************************************************************************** 22 */ 23 #include "unicode/uclean.h" 24 #include "cmemory.h" 25 #include "putilimp.h" 26 #include "uassert.h" 27 #include <stdlib.h> 28 29 /* uprv_malloc(0) returns a pointer to this read-only data. */ 30 static const int32_t zeroMem[] = {0, 0, 0, 0, 0, 0}; 31 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; 37 38 #if U_DEBUG && defined(UPRV_MALLOC_COUNT) 39 #include <stdio.h> 40 static int n=0; 41 static long b=0; 42 #endif 43 44 #if U_DEBUG 45 46 static char gValidMemorySink = 0; 47 48 U_CAPI void uprv_checkValidMemory(const void *p, size_t n) { 49 /* 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. 55 */ 56 const char *s = (const char *)p; 57 char c = gValidMemorySink; 58 size_t i; 59 U_ASSERT(p != NULL); 60 for(i = 0; i < n; ++i) { 61 c ^= s[i]; 62 } 63 gValidMemorySink = c; 64 } 65 66 #endif /* U_DEBUG */ 67 68 U_CAPI void * U_EXPORT2 69 uprv_malloc(size_t s) { 70 #if U_DEBUG && defined(UPRV_MALLOC_COUNT) 71 #if 1 72 putchar('>'); 73 fflush(stdout); 74 #else 75 fprintf(stderr,"MALLOC\t#%d\t%ul bytes\t%ul total\n", ++n,s,(b+=s)); fflush(stderr); 76 #endif 77 #endif 78 if (s > 0) { 79 if (pAlloc) { 80 return (*pAlloc)(pContext, s); 81 } else { 82 return uprv_default_malloc(s); 83 } 84 } else { 85 return (void *)zeroMem; 86 } 87 } 88 89 U_CAPI void * U_EXPORT2 90 uprv_realloc(void * buffer, size_t size) { 91 #if U_DEBUG && defined(UPRV_MALLOC_COUNT) 92 putchar('~'); 93 fflush(stdout); 94 #endif 95 if (buffer == zeroMem) { 96 return uprv_malloc(size); 97 } else if (size == 0) { 98 if (pFree) { 99 (*pFree)(pContext, buffer); 100 } else { 101 uprv_default_free(buffer); 102 } 103 return (void *)zeroMem; 104 } else { 105 if (pRealloc) { 106 return (*pRealloc)(pContext, buffer, size); 107 } else { 108 return uprv_default_realloc(buffer, size); 109 } 110 } 111 } 112 113 U_CAPI void U_EXPORT2 114 uprv_free(void *buffer) { 115 #if U_DEBUG && defined(UPRV_MALLOC_COUNT) 116 putchar('<'); 117 fflush(stdout); 118 #endif 119 if (buffer != zeroMem) { 120 if (pFree) { 121 (*pFree)(pContext, buffer); 122 } else { 123 uprv_default_free(buffer); 124 } 125 } 126 } 127 128 U_CAPI void * U_EXPORT2 129 uprv_calloc(size_t num, size_t size) { 130 void *mem = NULL; 131 size *= num; 132 mem = uprv_malloc(size); 133 if (mem) { 134 uprv_memset(mem, 0, size); 135 } 136 return mem; 137 } 138 139 U_CAPI void U_EXPORT2 140 u_setMemoryFunctions(const void *context, UMemAllocFn *a, UMemReallocFn *r, UMemFreeFn *f, UErrorCode *status) 141 { 142 if (U_FAILURE(*status)) { 143 return; 144 } 145 if (a==NULL || r==NULL || f==NULL) { 146 *status = U_ILLEGAL_ARGUMENT_ERROR; 147 return; 148 } 149 pContext = context; 150 pAlloc = a; 151 pRealloc = r; 152 pFree = f; 153 } 154 155 156 U_CFUNC UBool cmemory_cleanup(void) { 157 pContext = NULL; 158 pAlloc = NULL; 159 pRealloc = NULL; 160 pFree = NULL; 161 return TRUE; 162 } 163