Line data Source code
1 : // © 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 253 : 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 253 : const char *s = (const char *)p;
57 253 : char c = gValidMemorySink;
58 : size_t i;
59 253 : U_ASSERT(p != NULL);
60 506 : for(i = 0; i < n; ++i) {
61 253 : c ^= s[i];
62 : }
63 253 : gValidMemorySink = c;
64 253 : }
65 :
66 : #endif /* U_DEBUG */
67 :
68 : U_CAPI void * U_EXPORT2
69 82 : 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 82 : if (s > 0) {
79 82 : if (pAlloc) {
80 82 : return (*pAlloc)(pContext, s);
81 : } else {
82 0 : return uprv_default_malloc(s);
83 : }
84 : } else {
85 0 : return (void *)zeroMem;
86 : }
87 : }
88 :
89 : U_CAPI void * U_EXPORT2
90 0 : uprv_realloc(void * buffer, size_t size) {
91 : #if U_DEBUG && defined(UPRV_MALLOC_COUNT)
92 : putchar('~');
93 : fflush(stdout);
94 : #endif
95 0 : if (buffer == zeroMem) {
96 0 : return uprv_malloc(size);
97 0 : } else if (size == 0) {
98 0 : if (pFree) {
99 0 : (*pFree)(pContext, buffer);
100 : } else {
101 0 : uprv_default_free(buffer);
102 : }
103 0 : return (void *)zeroMem;
104 : } else {
105 0 : if (pRealloc) {
106 0 : return (*pRealloc)(pContext, buffer, size);
107 : } else {
108 0 : return uprv_default_realloc(buffer, size);
109 : }
110 : }
111 : }
112 :
113 : U_CAPI void U_EXPORT2
114 19 : uprv_free(void *buffer) {
115 : #if U_DEBUG && defined(UPRV_MALLOC_COUNT)
116 : putchar('<');
117 : fflush(stdout);
118 : #endif
119 19 : if (buffer != zeroMem) {
120 19 : if (pFree) {
121 19 : (*pFree)(pContext, buffer);
122 : } else {
123 0 : uprv_default_free(buffer);
124 : }
125 : }
126 19 : }
127 :
128 : U_CAPI void * U_EXPORT2
129 0 : uprv_calloc(size_t num, size_t size) {
130 0 : void *mem = NULL;
131 0 : size *= num;
132 0 : mem = uprv_malloc(size);
133 0 : if (mem) {
134 0 : uprv_memset(mem, 0, size);
135 : }
136 0 : return mem;
137 : }
138 :
139 : U_CAPI void U_EXPORT2
140 3 : u_setMemoryFunctions(const void *context, UMemAllocFn *a, UMemReallocFn *r, UMemFreeFn *f, UErrorCode *status)
141 : {
142 3 : if (U_FAILURE(*status)) {
143 0 : return;
144 : }
145 3 : if (a==NULL || r==NULL || f==NULL) {
146 0 : *status = U_ILLEGAL_ARGUMENT_ERROR;
147 0 : return;
148 : }
149 3 : pContext = context;
150 3 : pAlloc = a;
151 3 : pRealloc = r;
152 3 : pFree = f;
153 : }
154 :
155 :
156 0 : U_CFUNC UBool cmemory_cleanup(void) {
157 0 : pContext = NULL;
158 0 : pAlloc = NULL;
159 0 : pRealloc = NULL;
160 0 : pFree = NULL;
161 0 : return TRUE;
162 : }
|