00001
00002
00003
00004
00010 #if HAVE_CONFIG_H
00011 #include <config.h>
00012 #endif
00013
00014 #include <stdio.h>
00015 #include <stdlib.h>
00016 #include <string.h>
00017
00018 #include <yaz/log.h>
00019 #include <yaz/xmalloc.h>
00020
00021 #ifndef TRACE_XMALLOC
00022 #define TRACE_XMALLOC 1
00023 #endif
00024
00025 static int log_level=0;
00026 static int log_level_initialized=0;
00027
00028 #if TRACE_XMALLOC > 1
00029
00030 static const unsigned char head[] = {88, 77, 66, 55, 44, 33, 22, 11};
00031 static const unsigned char tail[] = {11, 22, 33, 44, 55, 66, 77, 88};
00032 static const unsigned char freed[] = {11, 22, 33, 44, 55, 66, 77, 88};
00033
00034 struct dmalloc_info {
00035 int len;
00036 char file[16];
00037 int line;
00038 struct dmalloc_info *next;
00039 struct dmalloc_info *prev;
00040 };
00041
00042 struct dmalloc_info *dmalloc_list = 0;
00043
00044
00045 void *xmalloc_d(size_t nbytes, const char *file, int line)
00046 {
00047 char *res;
00048 struct dmalloc_info *dinfo;
00049
00050 if (!log_level_initialized)
00051 {
00052 log_level=yaz_log_module_level("malloc");
00053 log_level_initialized=1;
00054 }
00055
00056 if (!(res = (char*) malloc(nbytes + sizeof(*dinfo)+16*sizeof(char))))
00057 return 0;
00058 dinfo = (struct dmalloc_info *) res;
00059 strncpy (dinfo->file, file, sizeof(dinfo->file)-1);
00060 dinfo->file[sizeof(dinfo->file)-1] = '\0';
00061 dinfo->line = line;
00062 dinfo->len = nbytes;
00063
00064 dinfo->prev = 0;
00065 dinfo->next = dmalloc_list;
00066 if (dinfo->next)
00067 dinfo->next->prev = dinfo;
00068 dmalloc_list = dinfo;
00069
00070 memcpy(res + sizeof(*dinfo), head, 8*sizeof(char));
00071 res += sizeof(*dinfo) + 8*sizeof(char);
00072 memcpy(res + nbytes, tail, 8*sizeof(char));
00073 return res;
00074 }
00075
00076 void xfree_d(void *ptr, const char *file, int line)
00077 {
00078 struct dmalloc_info *dinfo;
00079
00080 if (!ptr)
00081 return;
00082 dinfo = (struct dmalloc_info *)
00083 ((char*)ptr - 8*sizeof(char) - sizeof(*dinfo));
00084 if (memcmp(head, (char*) ptr - 8*sizeof(char), 8*sizeof(char)))
00085 {
00086 yaz_log(YLOG_FATAL, "xfree_d bad head, %s:%d, %p", file, line, ptr);
00087 abort();
00088 }
00089 if (memcmp((char*) ptr + dinfo->len, tail, 8*sizeof(char)))
00090 {
00091 yaz_log(YLOG_FATAL, "xfree_d bad tail, %s:%d, %p", file, line, ptr);
00092 abort();
00093 }
00094 if (dinfo->prev)
00095 dinfo->prev->next = dinfo->next;
00096 else
00097 dmalloc_list = dinfo->next;
00098 if (dinfo->next)
00099 dinfo->next->prev = dinfo->prev;
00100 memcpy ((char*) ptr - 8*sizeof(char), freed, 8*sizeof(char));
00101 free(dinfo);
00102 return;
00103 }
00104
00105 void *xrealloc_d(void *p, size_t nbytes, const char *file, int line)
00106 {
00107 struct dmalloc_info *dinfo;
00108 char *ptr = (char*) p;
00109 char *res;
00110
00111 if (!log_level_initialized)
00112 {
00113 log_level=yaz_log_module_level("malloc");
00114 log_level_initialized=1;
00115 }
00116
00117 if (!ptr)
00118 {
00119 if (!nbytes)
00120 return 0;
00121 res = (char *) malloc(nbytes + sizeof(*dinfo) + 16*sizeof(char));
00122 }
00123 else
00124 {
00125 if (memcmp(head, ptr - 8*sizeof(char), 8*sizeof(char)))
00126 {
00127 yaz_log(YLOG_FATAL, "xrealloc_d bad head, %s:%d, %p",
00128 file, line, ptr);
00129 abort();
00130 }
00131 dinfo = (struct dmalloc_info *) (ptr-8*sizeof(char) - sizeof(*dinfo));
00132 if (memcmp(ptr + dinfo->len, tail, 8*sizeof(char)))
00133 {
00134 yaz_log(YLOG_FATAL, "xrealloc_d bad tail, %s:%d, %p",
00135 file, line, ptr);
00136 abort();
00137 }
00138 if (dinfo->prev)
00139 dinfo->prev->next = dinfo->next;
00140 else
00141 dmalloc_list = dinfo->next;
00142 if (dinfo->next)
00143 dinfo->next->prev = dinfo->prev;
00144
00145 if (!nbytes)
00146 {
00147 free (dinfo);
00148 return 0;
00149 }
00150 res = (char *)
00151 realloc(dinfo, nbytes + sizeof(*dinfo) + 16*sizeof(char));
00152 }
00153 if (!res)
00154 return 0;
00155 dinfo = (struct dmalloc_info *) res;
00156 strncpy (dinfo->file, file, sizeof(dinfo->file)-1);
00157 dinfo->file[sizeof(dinfo->file)-1] = '\0';
00158 dinfo->line = line;
00159 dinfo->len = nbytes;
00160
00161 dinfo->prev = 0;
00162 dinfo->next = dmalloc_list;
00163 if (dmalloc_list)
00164 dmalloc_list->prev = dinfo;
00165 dmalloc_list = dinfo;
00166
00167 memcpy(res + sizeof(*dinfo), head, 8*sizeof(char));
00168 res += sizeof(*dinfo) + 8*sizeof(char);
00169 memcpy(res + nbytes, tail, 8*sizeof(char));
00170 return res;
00171 }
00172
00173 void *xcalloc_d(size_t nmemb, size_t size, const char *file, int line)
00174 {
00175 char *res;
00176 struct dmalloc_info *dinfo;
00177 size_t nbytes = nmemb * size;
00178
00179 if (!log_level_initialized)
00180 {
00181 log_level=yaz_log_module_level("malloc");
00182 log_level_initialized=1;
00183 }
00184
00185 if (!(res = (char*) calloc(1, nbytes+sizeof(*dinfo)+16*sizeof(char))))
00186 return 0;
00187 dinfo = (struct dmalloc_info *) res;
00188 strncpy (dinfo->file, file, sizeof(dinfo->file)-1);
00189 dinfo->file[sizeof(dinfo->file)-1] = '\0';
00190 dinfo->line = line;
00191 dinfo->len = nbytes;
00192
00193 dinfo->prev = 0;
00194 dinfo->next = dmalloc_list;
00195 if (dinfo->next)
00196 dinfo->next->prev = dinfo;
00197 dmalloc_list = dinfo;
00198
00199 memcpy(res + sizeof(*dinfo), head, 8*sizeof(char));
00200 res += sizeof(*dinfo) + 8*sizeof(char);
00201 memcpy(res + nbytes, tail, 8*sizeof(char));
00202 return res;
00203 }
00204
00205 void xmalloc_trav_d(const char *file, int line)
00206 {
00207 size_t size = 0;
00208 struct dmalloc_info *dinfo = dmalloc_list;
00209
00210 if (!log_level_initialized)
00211 {
00212 log_level=yaz_log_module_level("malloc");
00213 log_level_initialized=1;
00214 }
00215
00216 yaz_log (log_level, "malloc_trav %s:%d", file, line);
00217 while (dinfo)
00218 {
00219 yaz_log (log_level, " %20s:%d p=%p size=%d", dinfo->file, dinfo->line,
00220 ((char*) dinfo)+sizeof(*dinfo)+8*sizeof(char), dinfo->len);
00221 size += dinfo->len;
00222 dinfo = dinfo->next;
00223 }
00224 yaz_log (log_level, "total bytes %ld", (long) size);
00225 }
00226
00227 #else
00228
00229 #define xrealloc_d(o, x, f, l) realloc(o, x)
00230 #define xmalloc_d(x, f, l) malloc(x)
00231 #define xcalloc_d(x,y, f, l) calloc(x,y)
00232 #define xfree_d(x, f, l) free(x)
00233 #define xmalloc_trav_d(f, l)
00234 #endif
00235
00236 void xmalloc_trav_f(const char *s, const char *file, int line)
00237 {
00238 if (!log_level_initialized)
00239 {
00240 log_level=yaz_log_module_level("malloc");
00241 log_level_initialized=1;
00242 }
00243
00244 xmalloc_trav_d(file, line);
00245 }
00246
00247 void xmalloc_fatal(void)
00248 {
00249 exit(1);
00250 }
00251
00252 void *xrealloc_f (void *o, size_t size, const char *file, int line)
00253 {
00254 void *p = xrealloc_d (o, size, file, line);
00255
00256 if (!log_level_initialized)
00257 {
00258 log_level=yaz_log_module_level("malloc");
00259 log_level_initialized=1;
00260 }
00261
00262 if(log_level)
00263 yaz_log (log_level,
00264 "%s:%d: xrealloc(s=%ld) %p -> %p", file, line, (long) size, o, p);
00265 if (!p)
00266 {
00267 yaz_log (YLOG_FATAL|YLOG_ERRNO, "Out of memory, realloc (%ld bytes)",
00268 (long) size);
00269 xmalloc_fatal();
00270 }
00271 return p;
00272 }
00273
00274 void *xmalloc_f (size_t size, const char *file, int line)
00275 {
00276 void *p = xmalloc_d (size, file, line);
00277
00278 if (!log_level_initialized)
00279 {
00280 log_level=yaz_log_module_level("malloc");
00281 log_level_initialized=1;
00282 }
00283
00284 if (log_level)
00285 yaz_log (log_level, "%s:%d: xmalloc(s=%ld) %p", file, line,
00286 (long) size, p);
00287
00288 if (!p)
00289 {
00290 yaz_log (YLOG_FATAL, "Out of memory - malloc (%ld bytes)",
00291 (long) size);
00292 xmalloc_fatal();
00293 }
00294 return p;
00295 }
00296
00297 void *xcalloc_f (size_t nmemb, size_t size, const char *file, int line)
00298 {
00299 void *p = xcalloc_d (nmemb, size, file, line);
00300 if (!log_level_initialized)
00301 {
00302 log_level=yaz_log_module_level("malloc");
00303 log_level_initialized=1;
00304 }
00305
00306 if (log_level)
00307 yaz_log (log_level, "%s:%d: xcalloc(s=%ld) %p", file, line,
00308 (long) size, p);
00309
00310 if (!p)
00311 {
00312 yaz_log (YLOG_FATAL, "Out of memory - calloc (%ld, %ld)",
00313 (long) nmemb, (long) size);
00314 xmalloc_fatal();
00315 }
00316 return p;
00317 }
00318
00319 char *xstrdup_f (const char *s, const char *file, int line)
00320 {
00321 char *p = (char *)xmalloc_d (strlen(s)+1, file, line);
00322 if (!log_level_initialized)
00323 {
00324 log_level=yaz_log_module_level("malloc");
00325 log_level_initialized=1;
00326 }
00327
00328 if (log_level)
00329 yaz_log (log_level, "%s:%d: xstrdup(s=%ld) %p", file, line,
00330 (long) strlen(s)+1, p);
00331
00332 strcpy (p, s);
00333 return p;
00334 }
00335
00336 void xfree_f(void *p, const char *file, int line)
00337 {
00338 if (!p)
00339 return ;
00340 if (log_level)
00341 yaz_log (log_level, "%s:%d: xfree %p", file, line, p);
00342 xfree_d(p, file, line);
00343 }
00344
00345
00346
00347
00348
00349
00350
00351