SRW, CQL, 2003
[yaz-moved-to-github.git] / util / xmalloc.c
1 /*
2  * Copyright (C) 1994-2003, Index Data
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Id: xmalloc.c,v 1.18 2003-01-06 08:20:28 adam Exp $
7  */
8
9 #if HAVE_CONFIG_H
10 #include <config.h>
11 #endif
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16
17 #include <yaz/log.h>
18 #include <yaz/xmalloc.h>
19
20 #ifndef TRACE_XMALLOC
21 #define TRACE_XMALLOC 1
22 #endif
23
24 #if TRACE_XMALLOC > 1
25
26 static const unsigned char head[] = {44, 33, 22, 11};
27 static const unsigned char tail[] = {11, 22, 33, 44};
28 static const unsigned char freed[] = {11, 22, 33, 44};
29
30 struct dmalloc_info {
31     int len;
32     char file[16];
33     int line;
34     struct dmalloc_info *next;
35     struct dmalloc_info *prev;
36 };
37
38 struct dmalloc_info *dmalloc_list = 0;
39
40 void *xmalloc_d(size_t nbytes, const char *file, int line)
41 {
42     char *res;
43     struct dmalloc_info *dinfo;
44     
45     if (!(res = (char*) malloc(nbytes + sizeof(*dinfo)+8*sizeof(char))))
46         return 0;
47     dinfo = (struct dmalloc_info *) res;
48     strncpy (dinfo->file, file, sizeof(dinfo->file)-1);
49     dinfo->file[sizeof(dinfo->file)-1] = '\0';
50     dinfo->line = line;
51     dinfo->len = nbytes;
52     
53     dinfo->prev = 0;
54     dinfo->next = dmalloc_list;
55     if (dinfo->next)
56         dinfo->next->prev = dinfo;
57     dmalloc_list = dinfo;
58     
59     memcpy(res + sizeof(*dinfo), head, 4*sizeof(char));
60     res += sizeof(*dinfo) + 4*sizeof(char);
61     memcpy(res + nbytes, tail, 4*sizeof(char));
62     return res;
63 }
64
65 void xfree_d(void *ptr, const char *file, int line)
66 {
67     struct dmalloc_info *dinfo;
68
69     if (!ptr)
70         return;
71     dinfo = (struct dmalloc_info *)
72         ((char*)ptr - 4*sizeof(char) - sizeof(*dinfo));
73     if (memcmp(head, (char*) ptr - 4*sizeof(char), 4*sizeof(char)))
74     {
75         yaz_log(LOG_FATAL, "xfree_d bad head, %s:%d, %p", file, line, ptr);
76         abort();
77     }
78     if (memcmp((char*) ptr + dinfo->len, tail, 4*sizeof(char)))
79     {
80         yaz_log(LOG_FATAL, "xfree_d bad tail, %s:%d, %p", file, line, ptr);
81         abort();
82     }
83     if (dinfo->prev)
84         dinfo->prev->next = dinfo->next;
85     else
86         dmalloc_list = dinfo->next;
87     if (dinfo->next)
88         dinfo->next->prev = dinfo->prev;
89     memcpy ((char*) ptr - 4*sizeof(char), freed, 4*sizeof(char));
90     free(dinfo);
91     return;
92 }
93
94 void *xrealloc_d(void *p, size_t nbytes, const char *file, int line)
95 {
96     struct dmalloc_info *dinfo;
97     char *ptr = (char*) p;
98     char *res;
99     
100     if (!ptr)
101     {
102         if (!nbytes)
103             return 0;
104         res = (char *) malloc(nbytes + sizeof(*dinfo) + 8*sizeof(char));
105     }
106     else
107     {
108         if (memcmp(head, ptr - 4*sizeof(char), 4*sizeof(char)))
109         {
110             yaz_log(LOG_FATAL, "xrealloc_d bad head, %s:%d, %p",
111                     file, line, ptr);
112             abort();
113         }
114         dinfo = (struct dmalloc_info *) (ptr-4*sizeof(char) - sizeof(*dinfo));
115         if (memcmp(ptr + dinfo->len, tail, 4*sizeof(char)))
116         {
117             yaz_log(LOG_FATAL, "xrealloc_d bad tail, %s:%d, %p",
118                     file, line, ptr);
119             abort();
120         }
121         if (dinfo->prev)
122             dinfo->prev->next = dinfo->next;
123         else
124             dmalloc_list = dinfo->next;
125         if (dinfo->next)
126             dinfo->next->prev = dinfo->prev;
127         
128         if (!nbytes)
129         {
130             free (dinfo);
131             return 0;
132         }
133         res = (char *)
134             realloc(dinfo, nbytes + sizeof(*dinfo) + 8*sizeof(char));
135     }
136     if (!res)
137         return 0;
138     dinfo = (struct dmalloc_info *) res;
139     strncpy (dinfo->file, file, sizeof(dinfo->file)-1);
140     dinfo->file[sizeof(dinfo->file)-1] = '\0';
141     dinfo->line = line;
142     dinfo->len = nbytes;
143
144     dinfo->prev = 0;
145     dinfo->next = dmalloc_list;
146     if (dmalloc_list)
147         dmalloc_list->prev = dinfo;
148     dmalloc_list = dinfo;
149     
150     memcpy(res + sizeof(*dinfo), head, 4*sizeof(char));
151     res += sizeof(*dinfo) + 4*sizeof(char);
152     memcpy(res + nbytes, tail, 4*sizeof(char));
153     return res;
154 }
155
156 void *xcalloc_d(size_t nmemb, size_t size, const char *file, int line)
157 {
158     char *res;
159     struct dmalloc_info *dinfo;
160     size_t nbytes = nmemb * size;
161     
162     if (!(res = (char*) calloc(1, nbytes+sizeof(*dinfo)+8*sizeof(char))))
163         return 0;
164     dinfo = (struct dmalloc_info *) res;
165     strncpy (dinfo->file, file, sizeof(dinfo->file)-1);
166     dinfo->file[sizeof(dinfo->file)-1] = '\0';
167     dinfo->line = line;
168     dinfo->len = nbytes;
169     
170     dinfo->prev = 0;
171     dinfo->next = dmalloc_list;
172     if (dinfo->next)
173         dinfo->next->prev = dinfo;
174     dmalloc_list = dinfo;
175     
176     memcpy(res + sizeof(*dinfo), head, 4*sizeof(char));
177     res += sizeof(*dinfo) + 4*sizeof(char);
178     memcpy(res + nbytes, tail, 4*sizeof(char));
179     return res;
180 }
181
182 void xmalloc_trav_d(const char *file, int line)
183 {
184     size_t size = 0;
185     struct dmalloc_info *dinfo = dmalloc_list;
186     
187     yaz_log (LOG_MALLOC, "malloc_trav %s:%d", file, line);
188     while (dinfo)
189     {
190         yaz_log (LOG_MALLOC, " %20s:%d p=%p size=%d", dinfo->file, dinfo->line,
191               ((char*) dinfo)+sizeof(*dinfo)+4*sizeof(char), dinfo->len);
192         size += dinfo->len;
193         dinfo = dinfo->next;
194     }
195     yaz_log (LOG_MALLOC, "total bytes %ld", (long) size);
196 }
197
198 #else
199 /* TRACE_XMALLOC <= 1 */
200 #define xrealloc_d(o, x, f, l) realloc(o, x)
201 #define xmalloc_d(x, f, l) malloc(x)
202 #define xcalloc_d(x,y, f, l) calloc(x,y)
203 #define xfree_d(x, f, l) free(x)
204 #define xmalloc_trav_d(f, l) 
205 #endif
206
207 void xmalloc_trav_f(const char *s, const char *file, int line)
208 {
209     xmalloc_trav_d(file, line);
210 }
211
212 void *xrealloc_f (void *o, size_t size, const char *file, int line)
213 {
214     void *p = xrealloc_d (o, size, file, line);
215
216 #if TRACE_XMALLOC
217     yaz_log (LOG_MALLOC,
218             "%s:%d: xrealloc(s=%d) %p -> %p", file, line, size, o, p);
219 #endif
220     if (!p)
221     {
222         yaz_log (LOG_FATAL|LOG_ERRNO, "Out of memory, realloc (%d bytes)",
223                  size);
224         exit(1);
225     }
226     return p;
227 }
228
229 void *xmalloc_f (size_t size, const char *file, int line)
230 {
231     void *p = xmalloc_d (size, file, line);
232     
233 #if TRACE_XMALLOC
234     yaz_log (LOG_MALLOC, "%s:%d: xmalloc(s=%d) %p", file, line, size, p);
235 #endif
236     if (!p)
237     {
238         yaz_log (LOG_FATAL, "Out of memory - malloc (%d bytes)", size);
239         exit (1);
240     }
241     return p;
242 }
243
244 void *xcalloc_f (size_t nmemb, size_t size, const char *file, int line)
245 {
246     void *p = xcalloc_d (nmemb, size, file, line);
247 #if TRACE_XMALLOC
248     yaz_log (LOG_MALLOC, "%s:%d: xcalloc(s=%d) %p", file, line, size, p);
249 #endif
250     if (!p)
251     {
252         yaz_log (LOG_FATAL, "Out of memory - calloc (%d, %d)", nmemb, size);
253         exit (1);
254     }
255     return p;
256 }
257
258 char *xstrdup_f (const char *s, const char *file, int line)
259 {
260     char *p = (char *)xmalloc_d (strlen(s)+1, file, line);
261 #if TRACE_XMALLOC
262     yaz_log (LOG_MALLOC, "%s:%d: xstrdup(s=%d) %p", file, line, strlen(s)+1, p);
263 #endif
264     strcpy (p, s);
265     return p;
266 }
267
268 void xfree_f(void *p, const char *file, int line)
269 {
270     if (!p)
271         return ;
272 #if TRACE_XMALLOC
273     if (p)
274         yaz_log (LOG_MALLOC, "%s:%d: xfree %p", file, line, p);
275 #endif
276     xfree_d(p, file, line);
277 }