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