1 /* ====================================================================
2 * The Kannel Software License, Version 1.0
3 *
4 * Copyright (c) 2001-2014 Kannel Group
5 * Copyright (c) 1998-2001 WapIT Ltd.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. The end-user documentation included with the redistribution,
21 * if any, must include the following acknowledgment:
22 * "This product includes software developed by the
23 * Kannel Group (http://www.kannel.org/)."
24 * Alternately, this acknowledgment may appear in the software itself,
25 * if and wherever such third-party acknowledgments normally appear.
26 *
27 * 4. The names "Kannel" and "Kannel Group" must not be used to
28 * endorse or promote products derived from this software without
29 * prior written permission. For written permission, please
30 * contact org@kannel.org.
31 *
32 * 5. Products derived from this software may not be called "Kannel",
33 * nor may "Kannel" appear in their name, without prior written
34 * permission of the Kannel Group.
35 *
36 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39 * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS
40 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
41 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
42 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
45 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
46 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47 * ====================================================================
48 *
49 * This software consists of voluntary contributions made by many
50 * individuals on behalf of the Kannel Group. For more information on
51 * the Kannel Group, please see <http://www.kannel.org/>.
52 *
53 * Portions of this software are based upon software originally written at
54 * WapIT Ltd., Helsinki, Finland for the Kannel project.
55 */
56
57 /*
58 *
59 * wsalloc.c
60 *
61 * Author: Markku Rossi <mtr@iki.fi>
62 *
63 * Copyright (c) 1999-2000 WAPIT OY LTD.
64 * All rights reserved.
65 *
66 * Memory allocation routines. These are simple stub functions to fix
67 * some brain damages, found from some system's default allocators.
68 *
69 */
70
71 #include "wsint.h"
72
73 #if !WS_MEM_DEBUG
74
75 /********************* Global functions *********************************/
76
ws_malloc(size_t size)77 void *ws_malloc(size_t size)
78 {
79 return malloc(size);
80 }
81
82
ws_calloc(size_t num,size_t size)83 void *ws_calloc(size_t num, size_t size)
84 {
85 return calloc(num, size);
86 }
87
88
ws_realloc(void * ptr,size_t size)89 void *ws_realloc(void *ptr, size_t size)
90 {
91 if (size == 0) {
92 if (ptr)
93 free(ptr);
94
95 return NULL;
96 }
97
98 if (ptr == NULL)
99 return malloc(size);
100
101 return realloc(ptr, size);
102 }
103
104
ws_memdup(const void * ptr,size_t size)105 void *ws_memdup(const void *ptr, size_t size)
106 {
107 unsigned char *data = ws_malloc(size + 1);
108
109 if (data == NULL)
110 return NULL;
111
112 memcpy(data, ptr, size);
113 data[size] = '\0';
114
115 return data;
116 }
117
118
ws_strdup(const char * str)119 void *ws_strdup(const char *str)
120 {
121 size_t len;
122 void *s;
123
124 if (str == NULL)
125 return NULL;
126
127 len = strlen(str);
128 s = ws_malloc(len + 1);
129
130 if (s == NULL)
131 return NULL;
132
133 memcpy(s, str, len + 1);
134
135 return s;
136 }
137
138
ws_free(void * ptr)139 void ws_free(void *ptr)
140 {
141 if (ptr)
142 free(ptr);
143 }
144
145 #else /* WS_MEM_DEBUG */
146
147 /********************* Memory debugging routines ************************/
148
149 #define SIZE(_size) (sizeof(WsMemBlockHdr) + (_size))
150
151 #define MAGIC 0xfe01fa77
152
153 struct WsMemBlockHdrRec
154 {
155 unsigned long magic;
156 struct WsMemBlockHdrRec *next;
157 struct WsMemBlockHdrRec *prev;
158 size_t size;
159 const char *file;
160 int line;
161 };
162
163 typedef struct WsMemBlockHdrRec WsMemBlockHdr;
164
165 /* A linked list of currently allocated blocks. */
166 WsMemBlockHdr *blocks = NULL;
167
168 /* How many blocks are currently allocated. */
169 unsigned int num_blocks = 0;
170
171 /* The maximum amount of blocks used. */
172 unsigned int max_num_blocks = 0;
173
174 /* How many (user) bytes of memory the currently allocated blocks
175 use. */
176 size_t balance = 0;
177
178 /* The maximum amount of memory used. */
179 size_t max_balance = 0;
180
181 /* The alloc sequence number. */
182 unsigned int alloc_number = 0;
183
184 /* How many allocations are successful. */
185 unsigned int num_successful_allocs = -1;
186
187
add_block(WsMemBlockHdr * b,size_t size,const char * file,int line)188 static void add_block(WsMemBlockHdr *b, size_t size, const char *file, int line)
189 {
190 b->magic = MAGIC;
191
192 b->next = blocks;
193 b->prev = NULL;
194
195 if (blocks)
196 blocks->prev = b;
197
198 blocks = b;
199
200 b->size = size;
201 b->file = file;
202 b->line = line;
203
204 num_blocks++;
205 balance += size;
206
207 if (balance > max_balance)
208 max_balance = balance;
209
210 if (num_blocks > max_num_blocks)
211 max_num_blocks = num_blocks;
212 }
213
214
remove_block(WsMemBlockHdr * b)215 static void remove_block(WsMemBlockHdr *b)
216 {
217 if (b->magic != MAGIC)
218 ws_fatal("remove_block(): invalid magic\n");
219
220 if (b->next)
221 b->next->prev = b->prev;
222 if (b->prev)
223 b->prev->next = b->next;
224 else
225 blocks = b->next;
226
227 balance -= b->size;
228 num_blocks--;
229
230 memset(b, 0xfe, SIZE(b->size));
231 }
232
233
ws_malloc_i(size_t size,const char * file,int line)234 void *ws_malloc_i(size_t size, const char *file, int line)
235 {
236 WsMemBlockHdr *b;
237
238 if (alloc_number++ >= num_successful_allocs)
239 return NULL;
240
241 b = malloc(SIZE(size));
242
243 if (b == NULL)
244 return NULL;
245
246 add_block(b, size, file, line);
247
248 return b + 1;
249 }
250
251
ws_calloc_i(size_t num,size_t size,const char * file,int line)252 void *ws_calloc_i(size_t num, size_t size, const char *file, int line)
253 {
254 void *p = ws_malloc_i(num * size, file, line);
255
256 if (p)
257 memset(p, 0, num * size);
258
259 return p;
260 }
261
262
ws_realloc_i(void * ptr,size_t size,const char * file,int line)263 void *ws_realloc_i(void *ptr, size_t size, const char *file, int line)
264 {
265 WsMemBlockHdr *b = ((WsMemBlockHdr *) ptr) - 1;
266 void *n;
267
268 if (ptr == NULL)
269 return ws_malloc_i(size, file, line);
270
271 if (b->size >= size)
272 /* We can use the old block. */
273 return ptr;
274
275 /* Allocate a bigger block. */
276 n = ws_malloc_i(size, file, line);
277 if (n == NULL)
278 return NULL;
279
280 memcpy(n, ptr, b->size);
281
282 /* Free old block. */
283 remove_block(b);
284 free(b);
285
286 return n;
287 }
288
289
ws_memdup_i(const void * ptr,size_t size,const char * file,int line)290 void *ws_memdup_i(const void *ptr, size_t size, const char *file, int line)
291 {
292 void *p = ws_malloc_i(size + 1, file, line);
293
294 if (p) {
295 unsigned char *cp = (unsigned char *) p;
296
297 memcpy(p, ptr, size);
298 cp[size] = '\0';
299 }
300
301 return p;
302 }
303
304
ws_strdup_i(const char * str,const char * file,int line)305 void *ws_strdup_i(const char *str, const char *file, int line)
306 {
307 return ws_memdup_i(str, strlen(str), file, line);
308 }
309
310
ws_free_i(void * ptr)311 void ws_free_i(void *ptr)
312 {
313 WsMemBlockHdr *b = ((WsMemBlockHdr *) ptr) - 1;
314
315 if (ptr == NULL)
316 return;
317
318 remove_block(b);
319 free(b);
320 }
321
322
ws_has_leaks(void)323 int ws_has_leaks(void)
324 {
325 return num_blocks || balance;
326 }
327
328
ws_dump_blocks(void)329 void ws_dump_blocks(void)
330 {
331 WsMemBlockHdr *b;
332
333 fprintf(stderr, "ws: maximum memory usage: %u blocks, %ld bytes\n",
334 max_num_blocks, (long) max_balance);
335 fprintf(stderr, "ws: number of allocs: %u\n", alloc_number);
336
337 if (num_blocks || balance) {
338 fprintf(stderr, "ws: memory leaks: %u blocks, %ld bytes:\n",
339 num_blocks, (long) balance);
340
341 for (b = blocks; b; b = b->next)
342 fprintf(stderr, "%s:%d: %ld\n", b->file, b->line, (long) b->size);
343 }
344 }
345
346
ws_clear_leaks(unsigned int num_successful_allocs_)347 void ws_clear_leaks(unsigned int num_successful_allocs_)
348 {
349 alloc_number = 0;
350 num_successful_allocs = num_successful_allocs_;
351 blocks = NULL;
352 }
353
354 #endif /* WS_MEM_DEBUG */
355