Coverage Report

Created: 2025-07-11 06:23

/src/icu/source/common/cmemory.cpp
Line
Count
Source (jump to first uncovered line)
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
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
5.29M
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
5.29M
    if (s > 0) {
79
5.29M
        if (pAlloc) {
80
0
            return (*pAlloc)(pContext, s);
81
5.29M
        } else {
82
5.29M
            return uprv_default_malloc(s);
83
5.29M
        }
84
5.29M
    } else {
85
0
        return (void *)zeroMem;
86
0
    }
87
5.29M
}
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
0
        } else {
101
0
            uprv_default_free(buffer);
102
0
        }
103
0
        return (void *)zeroMem;
104
0
    } else {
105
0
        if (pRealloc) {
106
0
            return (*pRealloc)(pContext, buffer, size);
107
0
        } else {
108
0
            return uprv_default_realloc(buffer, size);
109
0
        }
110
0
    }
111
0
}
112
113
U_CAPI void U_EXPORT2
114
5.29M
uprv_free(void *buffer) {
115
#if U_DEBUG && defined(UPRV_MALLOC_COUNT)
116
  putchar('<');
117
  fflush(stdout);
118
#endif
119
5.29M
    if (buffer != zeroMem) {
120
5.29M
        if (pFree) {
121
0
            (*pFree)(pContext, buffer);
122
5.29M
        } else {
123
5.29M
            uprv_default_free(buffer);
124
5.29M
        }
125
5.29M
    }
126
5.29M
}
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
0
    }
136
0
    return mem;
137
0
}
138
139
U_CAPI void U_EXPORT2
140
u_setMemoryFunctions(const void *context, UMemAllocFn *a, UMemReallocFn *r, UMemFreeFn *f,  UErrorCode *status)
141
0
{
142
0
    if (U_FAILURE(*status)) {
143
0
        return;
144
0
    }
145
0
    if (a==NULL || r==NULL || f==NULL) {
146
0
        *status = U_ILLEGAL_ARGUMENT_ERROR;
147
0
        return;
148
0
    }
149
0
    pContext  = context;
150
0
    pAlloc    = a;
151
0
    pRealloc  = r;
152
0
    pFree     = f;
153
0
}
154
155
156
1.35k
U_CFUNC UBool cmemory_cleanup(void) {
157
1.35k
    pContext   = NULL;
158
1.35k
    pAlloc     = NULL;
159
1.35k
    pRealloc   = NULL;
160
1.35k
    pFree      = NULL;
161
1.35k
    return TRUE;
162
1.35k
}