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