Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

wsalloc.c

Go to the documentation of this file.
00001 /* ==================================================================== 
00002  * The Kannel Software License, Version 1.0 
00003  * 
00004  * Copyright (c) 2001-2008 Kannel Group  
00005  * Copyright (c) 1998-2001 WapIT Ltd.   
00006  * All rights reserved. 
00007  * 
00008  * Redistribution and use in source and binary forms, with or without 
00009  * modification, are permitted provided that the following conditions 
00010  * are met: 
00011  * 
00012  * 1. Redistributions of source code must retain the above copyright 
00013  *    notice, this list of conditions and the following disclaimer. 
00014  * 
00015  * 2. Redistributions in binary form must reproduce the above copyright 
00016  *    notice, this list of conditions and the following disclaimer in 
00017  *    the documentation and/or other materials provided with the 
00018  *    distribution. 
00019  * 
00020  * 3. The end-user documentation included with the redistribution, 
00021  *    if any, must include the following acknowledgment: 
00022  *       "This product includes software developed by the 
00023  *        Kannel Group (http://www.kannel.org/)." 
00024  *    Alternately, this acknowledgment may appear in the software itself, 
00025  *    if and wherever such third-party acknowledgments normally appear. 
00026  * 
00027  * 4. The names "Kannel" and "Kannel Group" must not be used to 
00028  *    endorse or promote products derived from this software without 
00029  *    prior written permission. For written permission, please  
00030  *    contact org@kannel.org. 
00031  * 
00032  * 5. Products derived from this software may not be called "Kannel", 
00033  *    nor may "Kannel" appear in their name, without prior written 
00034  *    permission of the Kannel Group. 
00035  * 
00036  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 
00037  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
00038  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
00039  * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS 
00040  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,  
00041  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  
00042  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR  
00043  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
00044  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE  
00045  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  
00046  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
00047  * ==================================================================== 
00048  * 
00049  * This software consists of voluntary contributions made by many 
00050  * individuals on behalf of the Kannel Group.  For more information on  
00051  * the Kannel Group, please see <http://www.kannel.org/>. 
00052  * 
00053  * Portions of this software are based upon software originally written at  
00054  * WapIT Ltd., Helsinki, Finland for the Kannel project.  
00055  */ 
00056 
00057 /*
00058  *
00059  * wsalloc.c
00060  *
00061  * Author: Markku Rossi <mtr@iki.fi>
00062  *
00063  * Copyright (c) 1999-2000 WAPIT OY LTD.
00064  *       All rights reserved.
00065  *
00066  * Memory allocation routines.  These are simple stub functions to fix
00067  * some brain damages, found from some system's default allocators.
00068  *
00069  */
00070 
00071 #include "wsint.h"
00072 
00073 #if !WS_MEM_DEBUG
00074 
00075 /********************* Global functions *********************************/
00076 
00077 void *ws_malloc(size_t size)
00078 {
00079     return malloc(size);
00080 }
00081 
00082 
00083 void *ws_calloc(size_t num, size_t size)
00084 {
00085     return calloc(num, size);
00086 }
00087 
00088 
00089 void *ws_realloc(void *ptr, size_t size)
00090 {
00091     if (size == 0) {
00092         if (ptr)
00093             free(ptr);
00094 
00095         return NULL;
00096     }
00097 
00098     if (ptr == NULL)
00099         return malloc(size);
00100 
00101     return realloc(ptr, size);
00102 }
00103 
00104 
00105 void *ws_memdup(const void *ptr, size_t size)
00106 {
00107     unsigned char *data = ws_malloc(size + 1);
00108 
00109     if (data == NULL)
00110         return NULL;
00111 
00112     memcpy(data, ptr, size);
00113     data[size] = '\0';
00114 
00115     return data;
00116 }
00117 
00118 
00119 void *ws_strdup(const char *str)
00120 {
00121     size_t len;
00122     void *s;
00123 
00124     if (str == NULL)
00125         return NULL;
00126 
00127     len = strlen(str);
00128     s = ws_malloc(len + 1);
00129 
00130     if (s == NULL)
00131         return NULL;
00132 
00133     memcpy(s, str, len + 1);
00134 
00135     return s;
00136 }
00137 
00138 
00139 void ws_free(void *ptr)
00140 {
00141     if (ptr)
00142         free(ptr);
00143 }
00144 
00145 #else /* WS_MEM_DEBUG */
00146 
00147 /********************* Memory debugging routines ************************/
00148 
00149 #define SIZE(_size) (sizeof(WsMemBlockHdr) + (_size))
00150 
00151 #define MAGIC 0xfe01fa77
00152 
00153 struct WsMemBlockHdrRec
00154 {
00155     unsigned long magic;
00156     struct WsMemBlockHdrRec *next;
00157     struct WsMemBlockHdrRec *prev;
00158     size_t size;
00159     const char *file;
00160     int line;
00161 };
00162 
00163 typedef struct WsMemBlockHdrRec WsMemBlockHdr;
00164 
00165 /* A linked list of currently allocated blocks. */
00166 WsMemBlockHdr *blocks = NULL;
00167 
00168 /* How many blocks are currently allocated. */
00169 unsigned int num_blocks = 0;
00170 
00171 /* The maximum amount of blocks used. */
00172 unsigned int max_num_blocks = 0;
00173 
00174 /* How many (user) bytes of memory the currently allocated blocks
00175 use. */
00176 size_t balance = 0;
00177 
00178 /* The maximum amount of memory used. */
00179 size_t max_balance = 0;
00180 
00181 /* The alloc sequence number. */
00182 unsigned int alloc_number = 0;
00183 
00184 /* How many allocations are successful. */
00185 unsigned int num_successful_allocs = -1;
00186 
00187 
00188 static void add_block(WsMemBlockHdr *b, size_t size, const char *file, int line)
00189 {
00190     b->magic = MAGIC;
00191 
00192     b->next = blocks;
00193     b->prev = NULL;
00194 
00195     if (blocks)
00196         blocks->prev = b;
00197 
00198     blocks = b;
00199 
00200     b->size = size;
00201     b->file = file;
00202     b->line = line;
00203 
00204     num_blocks++;
00205     balance += size;
00206 
00207     if (balance > max_balance)
00208         max_balance = balance;
00209 
00210     if (num_blocks > max_num_blocks)
00211         max_num_blocks = num_blocks;
00212 }
00213 
00214 
00215 static void remove_block(WsMemBlockHdr *b)
00216 {
00217     if (b->magic != MAGIC)
00218         ws_fatal("remove_block(): invalid magic\n");
00219 
00220     if (b->next)
00221         b->next->prev = b->prev;
00222     if (b->prev)
00223         b->prev->next = b->next;
00224     else
00225         blocks = b->next;
00226 
00227     balance -= b->size;
00228     num_blocks--;
00229 
00230     memset(b, 0xfe, SIZE(b->size));
00231 }
00232 
00233 
00234 void *ws_malloc_i(size_t size, const char *file, int line)
00235 {
00236     WsMemBlockHdr *b;
00237 
00238     if (alloc_number++ >= num_successful_allocs)
00239         return NULL;
00240 
00241     b = malloc(SIZE(size));
00242 
00243     if (b == NULL)
00244         return NULL;
00245 
00246     add_block(b, size, file, line);
00247 
00248     return b + 1;
00249 }
00250 
00251 
00252 void *ws_calloc_i(size_t num, size_t size, const char *file, int line)
00253 {
00254     void *p = ws_malloc_i(num * size, file, line);
00255 
00256     if (p)
00257         memset(p, 0, num * size);
00258 
00259     return p;
00260 }
00261 
00262 
00263 void *ws_realloc_i(void *ptr, size_t size, const char *file, int line)
00264 {
00265     WsMemBlockHdr *b = ((WsMemBlockHdr *) ptr) - 1;
00266     void *n;
00267 
00268     if (ptr == NULL)
00269         return ws_malloc_i(size, file, line);
00270 
00271     if (b->size >= size)
00272         /* We can use the old block. */
00273         return ptr;
00274 
00275     /* Allocate a bigger block. */
00276     n = ws_malloc_i(size, file, line);
00277     if (n == NULL)
00278         return NULL;
00279 
00280     memcpy(n, ptr, b->size);
00281 
00282     /* Free old block. */
00283     remove_block(b);
00284     free(b);
00285 
00286     return n;
00287 }
00288 
00289 
00290 void *ws_memdup_i(const void *ptr, size_t size, const char *file, int line)
00291 {
00292     void *p = ws_malloc_i(size + 1, file, line);
00293 
00294     if (p) {
00295         unsigned char *cp = (unsigned char *) p;
00296 
00297         memcpy(p, ptr, size);
00298         cp[size] = '\0';
00299     }
00300 
00301     return p;
00302 }
00303 
00304 
00305 void *ws_strdup_i(const char *str, const char *file, int line)
00306 {
00307     return ws_memdup_i(str, strlen(str), file, line);
00308 }
00309 
00310 
00311 void ws_free_i(void *ptr)
00312 {
00313     WsMemBlockHdr *b = ((WsMemBlockHdr *) ptr) - 1;
00314 
00315     if (ptr == NULL)
00316         return;
00317 
00318     remove_block(b);
00319     free(b);
00320 }
00321 
00322 
00323 int ws_has_leaks(void)
00324 {
00325     return num_blocks || balance;
00326 }
00327 
00328 
00329 void ws_dump_blocks(void)
00330 {
00331     WsMemBlockHdr *b;
00332 
00333     fprintf(stderr, "ws: maximum memory usage: %u blocks, %ld bytes\n",
00334             max_num_blocks, (long) max_balance);
00335     fprintf(stderr, "ws: number of allocs: %u\n", alloc_number);
00336 
00337     if (num_blocks || balance) {
00338         fprintf(stderr, "ws: memory leaks: %u blocks, %ld bytes:\n",
00339                 num_blocks, (long) balance);
00340 
00341         for (b = blocks; b; b = b->next)
00342             fprintf(stderr, "%s:%d: %ld\n", b->file, b->line, (long) b->size);
00343     }
00344 }
00345 
00346 
00347 void ws_clear_leaks(unsigned int num_successful_allocs_)
00348 {
00349     alloc_number = 0;
00350     num_successful_allocs = num_successful_allocs_;
00351     blocks = NULL;
00352 }
00353 
00354 #endif /* WS_MEM_DEBUG */
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.