blob: 07efdc8e2e3bce898d2d51769f66224d351f88ab [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001/******************************************************************************
2*(C) Copyright 2008 Marvell International Ltd.
3* All Rights Reserved
4******************************************************************************/
5/*****************************************************************************
6* Utility Library
7*
8* DESCRIPTION
9* Memory allocation wrapper functions. These wrapper functions provide
10* the following benefits:
11*
12* - Report failures using utlError so you don't need to every time you
13* call malloc/realloc/calloc.
14*
15* - Allow reported errors to include information about from where in
16* your source code the calls to malloc/realloc/calloc/free were made.
17* This is useful when trying to track down memory leaks.
18*
19* - Arranges for free'ed pointers to be assigned the value "NULL", to
20* better detect when an application attempts to access free'ed memory.
21*
22* - Makes it easier to later add test code to check for write-boundary
23* violations, memory leaks, and so forth (Future feature).
24*
25* EXAMPLE USAGE
26*
27* --- malloc/realloc ---
28* {
29* char *c_p;
30*
31* if ((c_p = utlMalloc(100 * sizeof(char))) == NULL)
32* <handle error here>
33*
34* <use `c_p' here>
35*
36* {
37* char *new_c_p;
38*
39* if ((new_c_p = utlRealloc(c_p, 200 * sizeof(char))) == NULL)
40* <handle error here>
41*
42* c_p = new_c_p;
43* }
44*
45* <use resize'ed `c_p' here>
46*
47* utlFree(c_p);
48* }
49*
50* --- malloc/realloc ---
51* {
52* char *c_p;
53*
54* if ((c_p = utlCalloc(100, sizeof(char))) == NULL)
55* <handle error here>
56*
57* <use `c_p' here>
58*
59* utlFree(c_p);
60* }
61*
62* Note: Use "utlFreeConst()" if you're trying to free a pointer that has
63* been declared as a "const". "utlFreeConst()" does not attempt
64* to NULL the just-free'ed pointer.
65*
66* Note: According to ANSI-C, if realloc() returns NULL, the block of
67* memory originally passed to realloc() remains allocated and
68* must eventually be free'ed to avoid a memory leak. Loosing
69* track of this original block is a very common programming
70* error.
71*
72*****************************************************************************/
73
74#include <stdio.h>
75
76#include "utlTypes.h"
77#include "utlError.h"
78#include "utlMalloc.h"
79#include "utlTrace.h"
80
81/*--- Configuration ---------------------------------------------------------*/
82
83/*--- for tracing heap allocs and frees ---*/
84#define utlTRACE_HEAP "heap"
85
86
87/*---------------------------------------------------------------------------*
88* FUNCTION
89* utlDoFree(utlHERE_DECLARATION, buf_p)
90* INPUT
91* utlHERE_DECLARATION == source of free request
92* buf_p == the buffer to free
93* OUTPUT
94* none
95* RETURNS
96* utlSUCCESS for success, utlFAILED for failure
97* DESCRIPTION
98* Free's one block of allocated memory.
99*---------------------------------------------------------------------------*/
100void utlDoFree(utlHERE_DECLARATION,
101 void *buf_p)
102{
103 utlTrace(utlTRACE_HEAP,
104 utlPrintTrace(utlDoFree, "%s/%s/line=%d, Free 0x%x\n",
105 utlHERE_FILE,
106 utlHERE_FUNC,
107 utlHERE_LINE,
108 (unsigned int)buf_p);
109 );
110
111 free(buf_p);
112}
113
114/*---------------------------------------------------------------------------*
115* FUNCTION
116* utlDoMalloc(utlHERE_DECLARATION, siz)
117* INPUT
118* utlHERE_DECLARATION == source of malloc request
119* siz == number of bytes to allocate
120* OUTPUT
121* none
122* RETURNS
123* utlSUCCESS for success, utlFAILED for failure
124* DESCRIPTION
125* Allocates one block of memory.
126*---------------------------------------------------------------------------*/
127void *utlDoMalloc(utlHERE_DECLARATION,
128 const size_t siz)
129{
130 void *buf_p;
131
132 if ((buf_p = malloc(siz)) == NULL)
133 {
134 utlError(utlDoMalloc, "Call to malloc(%d) failed\n", siz);
135 return NULL;
136 }
137
138 utlTrace(utlTRACE_HEAP,
139 utlPrintTrace(utlDoMalloc1, "%s/%s/line=%d, Malloc(%d bytes) 0x%x\n",
140 utlHERE_FILE,
141 utlHERE_FUNC,
142 utlHERE_LINE,
143 siz,
144 (unsigned int)buf_p);
145 );
146
147 return buf_p;
148}
149
150/*---------------------------------------------------------------------------*
151* FUNCTION
152* utlDoRealloc(utlHERE_DECLARATION, buf_p, siz)
153* INPUT
154* utlHERE_DECLARATION == source of realloc request
155* buf_p == pointer to the allocated block to be resized, or NULL
156* siz == number of bytes to allocate
157* OUTPUT
158* none
159* RETURNS
160* utlSUCCESS for success, utlFAILED for failure
161* DESCRIPTION
162* Resizes an allocated block of memory.
163*---------------------------------------------------------------------------*/
164void *utlDoRealloc(utlHERE_DECLARATION,
165 void *buf_p,
166 const size_t siz)
167{
168 void *new_buf_p;
169
170 if ((new_buf_p = realloc(buf_p, siz)) == NULL)
171 {
172 utlError(utlDoRealloc, "Call to realloc(0x%x, %d) failed\n", buf_p, siz);
173 return NULL;
174 }
175
176 utlTrace(utlTRACE_HEAP,
177 utlPrintTrace(utlDoRealloc1, "%s/%s/line=%d, Relloc(%d bytes) from 0x%x to 0x%x\n",
178 utlHERE_FILE,
179 utlHERE_FUNC,
180 utlHERE_LINE,
181 siz,
182 (unsigned int)buf_p,
183 (unsigned int)new_buf_p);
184 );
185
186 return new_buf_p;
187}
188
189/*---------------------------------------------------------------------------*
190* FUNCTION
191* utlDoCalloc(utlHERE_DECLARATION, number_of, siz)
192* INPUT
193* utlHERE_DECLARATION == source of calloc request
194* number_of == number of blocks to allocate
195* siz == number of bytes in each block
196* OUTPUT
197* none
198* RETURNS
199* utlSUCCESS for success, utlFAILED for failure
200* DESCRIPTION
201* Allocates and initializes multiple same-sized contigious blocks of
202* memory.
203*---------------------------------------------------------------------------*/
204void *utlDoCalloc(utlHERE_DECLARATION,
205 const size_t number_of,
206 const size_t siz)
207{
208 void *buf_p;
209
210 if ((buf_p = calloc(number_of, siz)) == NULL)
211 {
212 utlError(utlDoCalloc, "Call to calloc(%d, %d) failed\n", number_of, siz);
213 return NULL;
214 }
215
216 utlTrace(utlTRACE_HEAP,
217 utlPrintTrace(utlDoCalloc1, "%s/%s/line=%d, Calloc(%d %d-byte blocks) %p\n",
218 utlHERE_FILE,
219 utlHERE_FUNC,
220 utlHERE_LINE,
221 number_of,
222 siz,
223 buf_p);
224 );
225
226 return buf_p;
227}
228
229#ifdef utlTEST
230/*---------------------------------------------------------------------------*
231* FUNCTION
232* mallocTest()
233* INPUT
234* none
235* OUTPUT
236* none
237* RETURNS
238* "true" for pass, "false" for failure
239*---------------------------------------------------------------------------*/
240bool mallocTest(void)
241{
242 void *buf_p;
243
244 /*--- utlMalloc() -------------------------------------------------------*/
245
246 if ((buf_p = utlMalloc(10)) == NULL)
247 {
248 (void)fprintf(stderr, "memoryTest: utlMalloc() failed\n");
249 return false;
250 }
251 utlFree(buf_p);
252 if (buf_p != NULL)
253 {
254 (void)fprintf(stderr, "memoryTest: utlFree() failed\n");
255 return false;
256 }
257
258 /*--- utlRealloc() ------------------------------------------------------*/
259
260 if ((buf_p = utlMalloc(10)) == NULL)
261 {
262 (void)fprintf(stderr, "memoryTest: utlMalloc() failed\n");
263 return false;
264 }
265 if ((buf_p = utlRealloc(buf_p, 20)) == NULL)
266 {
267 (void)fprintf(stderr, "memoryTest: utlRealloc() failed\n");
268 return false;
269 }
270 utlFree(buf_p);
271 if (buf_p != NULL)
272 {
273 (void)fprintf(stderr, "memoryTest: utlFree() failed\n");
274 return false;
275 }
276
277 /*--- utlCalloc() -------------------------------------------------------*/
278
279 if ((buf_p = utlCalloc(10, 5)) == NULL)
280 {
281 (void)fprintf(stderr, "memoryTest: utlCalloc() failed\n");
282 return false;
283 }
284 utlFree(buf_p);
285 if (buf_p != NULL)
286 {
287 (void)fprintf(stderr, "memoryTest: utlFree() failed\n");
288 return false;
289 }
290
291 return true;
292}
293#endif /* utlTEST */
294