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