YAZ  5.34.0
xmalloc.c
Go to the documentation of this file.
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) Index Data
3  * See the file LICENSE for details.
4  */
10 #if HAVE_CONFIG_H
11 #include <config.h>
12 #endif
13 
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <assert.h>
18 
19 #include <yaz/log.h>
20 #include <yaz/xmalloc.h>
21 
22 #ifndef TRACE_XMALLOC
23 #define TRACE_XMALLOC 1
24 #endif
25 
26 /* treat any size >1/4 of max value of size_t to be an error */
27 #define MALLOC_SIZE_MAX ((size_t)(-1) / 4)
28 
29 static int log_level = 0;
30 static int log_level_initialized = 0;
31 
32 #if TRACE_XMALLOC > 1
33 
34 static const unsigned char head[] = {88, 77, 66, 55, 44, 33, 22, 11};
35 static const unsigned char tail[] = {11, 22, 33, 44, 55, 66, 77, 88};
36 static const unsigned char freed[] = {11, 22, 33, 44, 55, 66, 77, 88};
37 
38 struct dmalloc_info {
39  int len;
40  char file[16];
41  int line;
42  struct dmalloc_info *next;
43  struct dmalloc_info *prev;
44 };
45 
46 struct dmalloc_info *dmalloc_list = 0;
47 
48 
49 void *xmalloc_d(size_t nbytes, const char *file, int line)
50 {
51  char *res;
52  struct dmalloc_info *dinfo;
53 
55  {
56  log_level = yaz_log_module_level("malloc");
58  }
59 
60  if (!(res = (char*) malloc(nbytes + sizeof(*dinfo)+16*sizeof(char))))
61  return 0;
62  dinfo = (struct dmalloc_info *) res;
63  strncpy(dinfo->file, file, sizeof(dinfo->file)-1);
64  dinfo->file[sizeof(dinfo->file)-1] = '\0';
65  dinfo->line = line;
66  dinfo->len = nbytes;
67 
68  dinfo->prev = 0;
69  dinfo->next = dmalloc_list;
70  if (dinfo->next)
71  dinfo->next->prev = dinfo;
72  dmalloc_list = dinfo;
73 
74  memcpy(res + sizeof(*dinfo), head, 8*sizeof(char));
75  res += sizeof(*dinfo) + 8*sizeof(char);
76  memcpy(res + nbytes, tail, 8*sizeof(char));
77  return res;
78 }
79 
80 void xfree_d(void *ptr, const char *file, int line)
81 {
82  struct dmalloc_info *dinfo;
83 
84  if (!ptr)
85  return;
86  dinfo = (struct dmalloc_info *)
87  ((char*)ptr - 8*sizeof(char) - sizeof(*dinfo));
88  if (memcmp(head, (char*) ptr - 8*sizeof(char), 8*sizeof(char)))
89  {
90  yaz_log(YLOG_FATAL, "xfree_d bad head, %s:%d, %p", file, line, ptr);
91  abort();
92  }
93  if (memcmp((char*) ptr + dinfo->len, tail, 8*sizeof(char)))
94  {
95  yaz_log(YLOG_FATAL, "xfree_d bad tail, %s:%d, %p", file, line, ptr);
96  abort();
97  }
98  if (dinfo->prev)
99  dinfo->prev->next = dinfo->next;
100  else
101  dmalloc_list = dinfo->next;
102  if (dinfo->next)
103  dinfo->next->prev = dinfo->prev;
104  memcpy((char*) ptr - 8*sizeof(char), freed, 8*sizeof(char));
105  free(dinfo);
106  return;
107 }
108 
109 void *xrealloc_d(void *p, size_t nbytes, const char *file, int line)
110 {
111  struct dmalloc_info *dinfo;
112  char *ptr = (char*) p;
113  char *res;
114 
116  {
117  log_level = yaz_log_module_level("malloc");
119  }
120 
121  if (!ptr)
122  {
123  if (!nbytes)
124  return 0;
125  res = (char *) malloc(nbytes + sizeof(*dinfo) + 16*sizeof(char));
126  }
127  else
128  {
129  if (memcmp(head, ptr - 8*sizeof(char), 8*sizeof(char)))
130  {
131  yaz_log(YLOG_FATAL, "xrealloc_d bad head, %s:%d, %p",
132  file, line, ptr);
133  abort();
134  }
135  dinfo = (struct dmalloc_info *) (ptr-8*sizeof(char) - sizeof(*dinfo));
136  if (memcmp(ptr + dinfo->len, tail, 8*sizeof(char)))
137  {
138  yaz_log(YLOG_FATAL, "xrealloc_d bad tail, %s:%d, %p",
139  file, line, ptr);
140  abort();
141  }
142  if (dinfo->prev)
143  dinfo->prev->next = dinfo->next;
144  else
145  dmalloc_list = dinfo->next;
146  if (dinfo->next)
147  dinfo->next->prev = dinfo->prev;
148 
149  if (!nbytes)
150  {
151  free(dinfo);
152  return 0;
153  }
154  res = (char *)
155  realloc(dinfo, nbytes + sizeof(*dinfo) + 16*sizeof(char));
156  }
157  if (!res)
158  return 0;
159  dinfo = (struct dmalloc_info *) res;
160  strncpy(dinfo->file, file, sizeof(dinfo->file)-1);
161  dinfo->file[sizeof(dinfo->file)-1] = '\0';
162  dinfo->line = line;
163  dinfo->len = nbytes;
164 
165  dinfo->prev = 0;
166  dinfo->next = dmalloc_list;
167  if (dmalloc_list)
168  dmalloc_list->prev = dinfo;
169  dmalloc_list = dinfo;
170 
171  memcpy(res + sizeof(*dinfo), head, 8*sizeof(char));
172  res += sizeof(*dinfo) + 8*sizeof(char);
173  memcpy(res + nbytes, tail, 8*sizeof(char));
174  return res;
175 }
176 
177 void *xcalloc_d(size_t nmemb, size_t size, const char *file, int line)
178 {
179  char *res;
180  struct dmalloc_info *dinfo;
181  size_t nbytes = nmemb * size;
182 
184  {
185  log_level = yaz_log_module_level("malloc");
187  }
188 
189  if (!(res = (char*) calloc(1, nbytes+sizeof(*dinfo)+16*sizeof(char))))
190  return 0;
191  dinfo = (struct dmalloc_info *) res;
192  strncpy(dinfo->file, file, sizeof(dinfo->file)-1);
193  dinfo->file[sizeof(dinfo->file)-1] = '\0';
194  dinfo->line = line;
195  dinfo->len = nbytes;
196 
197  dinfo->prev = 0;
198  dinfo->next = dmalloc_list;
199  if (dinfo->next)
200  dinfo->next->prev = dinfo;
201  dmalloc_list = dinfo;
202 
203  memcpy(res + sizeof(*dinfo), head, 8*sizeof(char));
204  res += sizeof(*dinfo) + 8*sizeof(char);
205  memcpy(res + nbytes, tail, 8*sizeof(char));
206  return res;
207 }
208 
209 void xmalloc_trav_d(const char *file, int line)
210 {
211  size_t size = 0;
212  struct dmalloc_info *dinfo = dmalloc_list;
213 
215  {
216  log_level = yaz_log_module_level("malloc");
218  }
219 
220  yaz_log(log_level, "malloc_trav %s:%d", file, line);
221  while (dinfo)
222  {
223  yaz_log(log_level, " %20s:%d p=%p size=%d", dinfo->file, dinfo->line,
224  ((char*) dinfo)+sizeof(*dinfo)+8*sizeof(char), dinfo->len);
225  size += dinfo->len;
226  dinfo = dinfo->next;
227  }
228  yaz_log(log_level, "total bytes %ld", (long) size);
229 }
230 
231 #else
232 /* TRACE_XMALLOC <= 1 */
233 #define xrealloc_d(o, x, f, l) realloc(o, x)
234 #define xmalloc_d(x, f, l) malloc(x)
235 #define xcalloc_d(x,y, f, l) calloc(x,y)
236 #define xfree_d(x, f, l) free(x)
237 #define xmalloc_trav_d(f, l)
238 #endif
239 
240 void xmalloc_trav_f(const char *s, const char *file, int line)
241 {
243  {
244  log_level = yaz_log_module_level("malloc");
246  }
247 
248  xmalloc_trav_d(file, line);
249 }
250 
251 void xmalloc_fatal(size_t size)
252 {
253  assert(size < MALLOC_SIZE_MAX);
254  exit(1);
255 }
256 
257 void *xrealloc_f(void *o, size_t size, const char *file, int line)
258 {
259  void *p = xrealloc_d(o, size, file, line);
260 
262  {
263  log_level = yaz_log_module_level("malloc");
265  }
266 
267  if (log_level)
269  "%s:%d: xrealloc(s=%ld) %p -> %p", file, line, (long) size, o, p);
270  if (!p)
271  {
272  yaz_log(YLOG_FATAL, "%s:%d: Out of memory, realloc(%ld bytes)",
273  file, line, (long) size);
274  xmalloc_fatal(size);
275  }
276  return p;
277 }
278 
279 void *xmalloc_f(size_t size, const char *file, int line)
280 {
281  void *p = xmalloc_d(size, file, line);
282 
284  {
285  log_level = yaz_log_module_level("malloc");
287  }
288 
289  if (log_level)
290  yaz_log(log_level, "%s:%d: xmalloc(s=%ld) %p", file, line,
291  (long) size, p);
292 
293  if (!p)
294  {
295  yaz_log(YLOG_FATAL, "%s:%d: Out of memory - malloc(%ld bytes)",
296  file, line, (long) size);
297  xmalloc_fatal(size);
298  }
299  return p;
300 }
301 
302 void *xcalloc_f(size_t nmemb, size_t size, const char *file, int line)
303 {
304  void *p = xcalloc_d(nmemb, size, file, line);
306  {
307  log_level = yaz_log_module_level("malloc");
309  }
310 
311  if (log_level)
312  yaz_log(log_level, "%s:%d: xcalloc(s=%ld) %p", file, line,
313  (long) size, p);
314 
315  if (!p)
316  {
317  yaz_log(YLOG_FATAL, "%s:%d: Out of memory - calloc(%ld, %ld)",
318  file, line, (long) nmemb, (long) size);
319  xmalloc_fatal(size);
320  }
321  return p;
322 }
323 
324 char *xstrdup_f(const char *s, const char *file, int line)
325 {
326  char *p = (char *)xmalloc_d(strlen(s)+1, file, line);
328  {
329  log_level = yaz_log_module_level("malloc");
331  }
332 
333  if (log_level)
334  yaz_log(log_level, "%s:%d: xstrdup(s=%ld) %p", file, line,
335  (long) strlen(s)+1, p);
336 
337  strcpy(p, s);
338  return p;
339 }
340 
341 void xfree_f(void *p, const char *file, int line)
342 {
343  if (!p)
344  return ;
345  if (log_level)
346  yaz_log(log_level, "%s:%d: xfree %p", file, line, p);
347  xfree_d(p, file, line);
348 }
349 
350 char *xstrndup_f(const char *s, size_t n, const char *file, int line)
351 {
352  size_t l = strlen(s);
353  if (l < n)
354  return xstrdup_f(s, file, line);
355  {
356  char *a = (char*) xmalloc_f(n+1, file, line);
357  memcpy(a, s, n);
358  a[n] = '\0';
359  return a;
360  }
361 }
362 
363 /*
364  * Local variables:
365  * c-basic-offset: 4
366  * c-file-style: "Stroustrup"
367  * indent-tabs-mode: nil
368  * End:
369  * vim: shiftwidth=4 tabstop=8 expandtab
370  */
371 
void * malloc(YYSIZE_T)
void free(void *)
void yaz_log(int level, const char *fmt,...)
Writes log message.
Definition: log.c:487
int yaz_log_module_level(const char *name)
returns level for module
Definition: log.c:586
Logging utility.
#define YLOG_FATAL
log level: fatal
Definition: log.h:42
#define xfree_d(x, f, l)
Definition: xmalloc.c:236
#define xmalloc_trav_d(f, l)
Definition: xmalloc.c:237
char * xstrndup_f(const char *s, size_t n, const char *file, int line)
strndup
Definition: xmalloc.c:350
void * xrealloc_f(void *o, size_t size, const char *file, int line)
realloc
Definition: xmalloc.c:257
#define xcalloc_d(x, y, f, l)
Definition: xmalloc.c:235
void xmalloc_trav_f(const char *s, const char *file, int line)
logs all xmalloc buffers
Definition: xmalloc.c:240
#define xrealloc_d(o, x, f, l)
Definition: xmalloc.c:233
static int log_level
Definition: xmalloc.c:29
#define MALLOC_SIZE_MAX
Definition: xmalloc.c:27
#define xmalloc_d(x, f, l)
Definition: xmalloc.c:234
static int log_level_initialized
Definition: xmalloc.c:30
void xmalloc_fatal(size_t size)
Definition: xmalloc.c:251
void xfree_f(void *p, const char *file, int line)
free
Definition: xmalloc.c:341
void * xcalloc_f(size_t nmemb, size_t size, const char *file, int line)
calloc
Definition: xmalloc.c:302
char * xstrdup_f(const char *s, const char *file, int line)
strdup
Definition: xmalloc.c:324
void * xmalloc_f(size_t size, const char *file, int line)
malloc
Definition: xmalloc.c:279
Header for memory handling functions.