Set TRACE_XMALLOC to 1.
[yaz-moved-to-github.git] / util / xmalloc.c
1 /*
2  * Copyright (C) 1994-1999, Index Data
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: xmalloc.c,v $
7  * Revision 1.9  1999-09-10 08:58:32  adam
8  * Set TRACE_XMALLOC to 1.
9  *
10  * Revision 1.8  1999/08/27 09:40:32  adam
11  * Renamed logf function to yaz_log. Removed VC++ project files.
12  *
13  * Revision 1.7  1999/07/13 13:24:53  adam
14  * Updated memory debugging memory allocatation routines.
15  *
16  * Revision 1.6  1998/02/11 11:53:36  adam
17  * Changed code so that it compiles as C++.
18  *
19  * Revision 1.5  1997/10/31 12:20:09  adam
20  * Improved memory debugging for xmalloc/nmem.c. References to NMEM
21  * instead of ODR in n ESPEC-1 handling in source d1_espec.c.
22  * Bug fix: missing fclose in data1_read_espec1.
23  *
24  * Revision 1.4  1996/07/03 13:21:36  adam
25  * Function xfree_f checks for NULL pointer.
26  *
27  * Revision 1.3  1995/12/05  15:08:44  adam
28  * Fixed verbose of xrealloc.
29  *
30  * Revision 1.2  1995/12/05  11:08:37  adam
31  * More verbose malloc routines.
32  *
33  * Revision 1.1  1995/11/01  11:56:53  quinn
34  * Added Xmalloc.
35  *
36  * Revision 1.6  1995/10/16  14:03:11  quinn
37  * Changes to support element set names and espec1
38  *
39  * Revision 1.5  1995/09/04  12:34:06  adam
40  * Various cleanup. YAZ util used instead.
41  *
42  * Revision 1.4  1994/10/05  10:16:16  quinn
43  * Added xrealloc. Fixed bug in log.
44  *
45  * Revision 1.3  1994/09/26  16:31:37  adam
46  * Added xcalloc_f.
47  *
48  * Revision 1.2  1994/08/18  08:23:26  adam
49  * Res.c now use handles. xmalloc defines xstrdup.
50  *
51  * Revision 1.1  1994/08/17  13:37:54  adam
52  * xmalloc.c added to util.
53  *
54  */
55
56 #include <stdio.h>
57 #include <stdlib.h>
58 #include <string.h>
59
60 #include <log.h>
61 #include <xmalloc.h>
62
63 #define TRACE_XMALLOC 1
64
65 #if TRACE_XMALLOC > 1
66
67 static const unsigned char head[] = {44, 33, 22, 11};
68 static const unsigned char tail[] = {11, 22, 33, 44};
69 static const unsigned char freed[] = {11, 22, 33, 44};
70
71 struct dmalloc_info {
72     int len;
73     char file[16];
74     int line;
75     struct dmalloc_info *next;
76     struct dmalloc_info *prev;
77 };
78
79 struct dmalloc_info *dmalloc_list = 0;
80
81 void *xmalloc_d(size_t nbytes, const char *file, int line)
82 {
83     char *res;
84     struct dmalloc_info *dinfo;
85     
86     if (!(res = (char*) malloc(nbytes + sizeof(*dinfo)+8*sizeof(char))))
87         return 0;
88     dinfo = (struct dmalloc_info *) res;
89     strncpy (dinfo->file, file, sizeof(dinfo->file)-1);
90     dinfo->file[sizeof(dinfo->file)-1] = '\0';
91     dinfo->line = line;
92     dinfo->len = nbytes;
93     
94     dinfo->prev = 0;
95     dinfo->next = dmalloc_list;
96     if (dinfo->next)
97         dinfo->next->prev = dinfo;
98     dmalloc_list = dinfo;
99     
100     memcpy(res + sizeof(*dinfo), head, 4*sizeof(char));
101     res += sizeof(*dinfo) + 4*sizeof(char);
102     memcpy(res + nbytes, tail, 4*sizeof(char));
103     return res;
104 }
105
106 void xfree_d(void *ptr, const char *file, int line)
107 {
108     struct dmalloc_info *dinfo;
109
110     if (!ptr)
111         return;
112     dinfo = (struct dmalloc_info *)
113         ((char*)ptr - 4*sizeof(char) - sizeof(*dinfo));
114     if (memcmp(head, (char*) ptr - 4*sizeof(char), 4*sizeof(char)))
115     {
116         yaz_log(LOG_FATAL, "xfree_d bad head, %s:%d, %p", file, line, ptr);
117         abort();
118     }
119     if (memcmp((char*) ptr + dinfo->len, tail, 4*sizeof(char)))
120     {
121         yaz_log(LOG_FATAL, "xfree_d bad tail, %s:%d, %p", file, line, ptr);
122         abort();
123     }
124     if (dinfo->prev)
125         dinfo->prev->next = dinfo->next;
126     else
127         dmalloc_list = dinfo->next;
128     if (dinfo->next)
129         dinfo->next->prev = dinfo->prev;
130     memcpy ((char*) ptr - 4*sizeof(char), freed, 4*sizeof(char));
131     free(dinfo);
132     return;
133 }
134
135 void *xrealloc_d(void *p, size_t nbytes, const char *file, int line)
136 {
137     struct dmalloc_info *dinfo;
138     char *ptr = (char*) p;
139     char *res;
140     
141     if (!ptr)
142     {
143         if (!nbytes)
144             return 0;
145         res = (char *) malloc(nbytes + sizeof(*dinfo) + 8*sizeof(char));
146     }
147     else
148     {
149         if (memcmp(head, ptr - 4*sizeof(char), 4*sizeof(char)))
150         {
151             yaz_log(LOG_FATAL, "xrealloc_d bad head, %s:%d, %p",
152                     file, line, ptr);
153             abort();
154         }
155         dinfo = (struct dmalloc_info *) (ptr-4*sizeof(char) - sizeof(*dinfo));
156         if (memcmp(ptr + dinfo->len, tail, 4*sizeof(char)))
157         {
158             yaz_log(LOG_FATAL, "xrealloc_d bad tail, %s:%d, %p",
159                     file, line, ptr);
160             abort();
161         }
162         if (dinfo->prev)
163             dinfo->prev->next = dinfo->next;
164         else
165             dmalloc_list = dinfo->next;
166         if (dinfo->next)
167             dinfo->next->prev = dinfo->prev;
168         
169         if (!nbytes)
170         {
171             free (dinfo);
172             return 0;
173         }
174         res = (char *)
175             realloc(dinfo, nbytes + sizeof(*dinfo) + 8*sizeof(char));
176     }
177     if (!res)
178         return 0;
179     dinfo = (struct dmalloc_info *) res;
180     strncpy (dinfo->file, file, sizeof(dinfo->file)-1);
181     dinfo->file[sizeof(dinfo->file)-1] = '\0';
182     dinfo->line = line;
183     dinfo->len = nbytes;
184
185     dinfo->prev = 0;
186     dinfo->next = dmalloc_list;
187     if (dmalloc_list)
188         dmalloc_list->prev = dinfo;
189     dmalloc_list = dinfo;
190     
191     memcpy(res + sizeof(*dinfo), head, 4*sizeof(char));
192     res += sizeof(*dinfo) + 4*sizeof(char);
193     memcpy(res + nbytes, tail, 4*sizeof(char));
194     return res;
195 }
196
197 void *xcalloc_d(size_t nmemb, size_t size, const char *file, int line)
198 {
199     char *res;
200     struct dmalloc_info *dinfo;
201     size_t nbytes = nmemb * size;
202     
203     if (!(res = (char*) calloc(1, nbytes+sizeof(*dinfo)+8*sizeof(char))))
204         return 0;
205     dinfo = (struct dmalloc_info *) res;
206     strncpy (dinfo->file, file, sizeof(dinfo->file)-1);
207     dinfo->file[sizeof(dinfo->file)-1] = '\0';
208     dinfo->line = line;
209     dinfo->len = nbytes;
210     
211     dinfo->prev = 0;
212     dinfo->next = dmalloc_list;
213     if (dinfo->next)
214         dinfo->next->prev = dinfo;
215     dmalloc_list = dinfo;
216     
217     memcpy(res + sizeof(*dinfo), head, 4*sizeof(char));
218     res += sizeof(*dinfo) + 4*sizeof(char);
219     memcpy(res + nbytes, tail, 4*sizeof(char));
220     return res;
221 }
222
223 void xmalloc_trav_d(const char *file, int line)
224 {
225     size_t size = 0;
226     struct dmalloc_info *dinfo = dmalloc_list;
227     
228     yaz_log (LOG_LOG, "malloc_trav %s:%d", file, line);
229     while (dinfo)
230     {
231         yaz_log (LOG_LOG, " %20s:%d p=%p size=%d", dinfo->file, dinfo->line,
232               dinfo+sizeof(*dinfo)+4*sizeof(char), dinfo->len);
233         size += dinfo->len;
234         dinfo = dinfo->next;
235     }
236     yaz_log (LOG_LOG, "total bytes %ld", (long) size);
237 }
238
239 #else
240 /* TRACE_XMALLOC <= 1 */
241 #define xrealloc_d(o, x, f, l) realloc(o, x)
242 #define xmalloc_d(x, f, l) malloc(x)
243 #define xcalloc_d(x,y, f, l) calloc(x,y)
244 #define xfree_d(x, f, l) free(x)
245 #define xmalloc_trav_d(f, l) 
246 #endif
247
248 void xmalloc_trav_f(const char *s, const char *file, int line)
249 {
250     xmalloc_trav_d(file, line);
251 }
252
253 void *xrealloc_f (void *o, size_t size, const char *file, int line)
254 {
255     void *p = xrealloc_d (o, size, file, line);
256
257 #if TRACE_XMALLOC
258     yaz_log (LOG_DEBUG,
259             "%s:%d: xrealloc(s=%d) %p -> %p", file, line, size, o, p);
260 #endif
261     if (!p)
262     {
263         yaz_log (LOG_FATAL|LOG_ERRNO, "Out of memory, realloc (%d bytes)",
264                  size);
265         exit(1);
266     }
267     return p;
268 }
269
270 void *xmalloc_f (size_t size, const char *file, int line)
271 {
272     void *p = xmalloc_d (size, file, line);
273     
274 #if TRACE_XMALLOC
275     yaz_log (LOG_DEBUG, "%s:%d: xmalloc(s=%d) %p", file, line, size, p);
276 #endif
277     if (!p)
278     {
279         yaz_log (LOG_FATAL, "Out of memory - malloc (%d bytes)", size);
280         exit (1);
281     }
282     return p;
283 }
284
285 void *xcalloc_f (size_t nmemb, size_t size, const char *file, int line)
286 {
287     void *p = xcalloc_d (nmemb, size, file, line);
288 #if TRACE_XMALLOC
289     yaz_log (LOG_DEBUG, "%s:%d: xcalloc(s=%d) %p", file, line, size, p);
290 #endif
291     if (!p)
292     {
293         yaz_log (LOG_FATAL, "Out of memory - calloc (%d, %d)", nmemb, size);
294         exit (1);
295     }
296     return p;
297 }
298
299 char *xstrdup_f (const char *s, const char *file, int line)
300 {
301     char *p = (char *)xmalloc_d (strlen(s)+1, file, line);
302 #if TRACE_XMALLOC
303     yaz_log (LOG_DEBUG, "%s:%d: xstrdup(s=%d) %p", file, line, strlen(s)+1, p);
304 #endif
305     strcpy (p, s);
306     return p;
307 }
308
309 void xfree_f(void *p, const char *file, int line)
310 {
311     if (!p)
312         return ;
313 #if TRACE_XMALLOC
314     if (p)
315         yaz_log (LOG_DEBUG, "%s:%d: xfree %p", file, line, p);
316 #endif
317     xfree_d(p, file, line);
318 }