Kannel: Open Source WAP and SMS gateway  $Revision: 5037 $
wsalloc.c
Go to the documentation of this file.
1 /* ====================================================================
2  * The Kannel Software License, Version 1.0
3  *
4  * Copyright (c) 2001-2016 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 
77 void *ws_malloc(size_t size)
78 {
79  return malloc(size);
80 }
81 
82 
83 void *ws_calloc(size_t num, size_t size)
84 {
85  return calloc(num, size);
86 }
87 
88 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
323 int ws_has_leaks(void)
324 {
325  return num_blocks || balance;
326 }
327 
328 
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 
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 */
void ws_fatal(char *fmt,...)
Definition: wserror.c:91
void * ws_calloc(size_t num, size_t size)
Definition: wsalloc.c:83
int size
Definition: wsasm.c:84
void ws_free(void *ptr)
Definition: wsalloc.c:139
void * ws_realloc(void *ptr, size_t size)
Definition: wsalloc.c:89
#define calloc(a, b)
Definition: gwmem.h:192
#define realloc(p, n)
Definition: gwmem.h:193
FILE * file
Definition: log.c:133
#define free(p)
Definition: gwmem.h:194
void * ws_memdup(const void *ptr, size_t size)
Definition: wsalloc.c:105
#define malloc(n)
Definition: gwmem.h:191
void * ws_strdup(const char *str)
Definition: wsalloc.c:119
void * ws_malloc(size_t size)
Definition: wsalloc.c:77
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.