YAZ 5.35.1
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
29static int log_level = 0;
30static int log_level_initialized = 0;
31
32#if TRACE_XMALLOC > 1
33
34static const unsigned char head[] = {88, 77, 66, 55, 44, 33, 22, 11};
35static const unsigned char tail[] = {11, 22, 33, 44, 55, 66, 77, 88};
36static const unsigned char freed[] = {11, 22, 33, 44, 55, 66, 77, 88};
37
38struct dmalloc_info {
39 int len;
40 char file[16];
41 int line;
42 struct dmalloc_info *next;
43 struct dmalloc_info *prev;
44};
45
46struct dmalloc_info *dmalloc_list = 0;
47
48
49void *xmalloc_d(size_t nbytes, const char *file, int line)
50{
51 char *res;
52 struct dmalloc_info *dinfo;
53
55 {
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
80void 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
109void *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 {
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
177void *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 {
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
209void xmalloc_trav_d(const char *file, int line)
210{
211 size_t size = 0;
212 struct dmalloc_info *dinfo = dmalloc_list;
213
215 {
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
240void xmalloc_trav_f(const char *s, const char *file, int line)
241{
243 {
246 }
247
248 xmalloc_trav_d(file, line);
249}
250
251void xmalloc_fatal(size_t size)
252{
253 assert(size < MALLOC_SIZE_MAX);
254 exit(1);
255}
256
257void *xrealloc_f(void *o, size_t size, const char *file, int line)
258{
259 void *p = xrealloc_d(o, size, file, line);
260
262 {
265 }
266
267 if (log_level)
269 "%s:%d: xrealloc(s=%ld) %p", file, line, (long) size, 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
279void *xmalloc_f(size_t size, const char *file, int line)
280{
281 void *p = xmalloc_d(size, file, line);
282
284 {
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
302void *xcalloc_f(size_t nmemb, size_t size, const char *file, int line)
303{
304 void *p = xcalloc_d(nmemb, size, file, line);
306 {
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
324char *xstrdup_f(const char *s, const char *file, int line)
325{
326 char *p = (char *)xmalloc_d(strlen(s)+1, file, line);
328 {
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
341void 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
350char *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
void * xrealloc_f(void *o, size_t size, const char *file, int line)
realloc
Definition xmalloc.c:257
void * xcalloc_f(size_t nmemb, size_t size, const char *file, int line)
calloc
Definition xmalloc.c:302
#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
void * xmalloc_f(size_t size, const char *file, int line)
malloc
Definition xmalloc.c:279
static int log_level_initialized
Definition xmalloc.c:30
char * xstrdup_f(const char *s, const char *file, int line)
strdup
Definition xmalloc.c:324
char * xstrndup_f(const char *s, size_t n, const char *file, int line)
strndup
Definition xmalloc.c:350
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
Header for memory handling functions.