blob: 6f16c4b3caf5f46b909d63cd9effd681f7eeb00f [file] [log] [blame]
Owen Taylor3473f882001-02-23 17:55:21 +00001/*
Daniel Veillard26908ab2002-01-01 16:50:03 +00002 * xmlmemory.c: libxml memory allocator wrapper.
Owen Taylor3473f882001-02-23 17:55:21 +00003 *
Daniel Veillardc5d64342001-06-24 12:13:24 +00004 * daniel@veillard.com
Owen Taylor3473f882001-02-23 17:55:21 +00005 */
6
Daniel Veillard34ce8be2002-03-18 19:37:11 +00007#define IN_LIBXML
Bjorn Reese70a9da52001-04-21 16:57:29 +00008#include "libxml.h"
Owen Taylor3473f882001-02-23 17:55:21 +00009
Owen Taylor3473f882001-02-23 17:55:21 +000010#include <string.h>
11
12#ifdef HAVE_SYS_TYPES_H
13#include <sys/types.h>
14#endif
Daniel Veillard0ba59232002-02-10 13:20:39 +000015
Owen Taylor3473f882001-02-23 17:55:21 +000016#ifdef HAVE_TIME_H
17#include <time.h>
18#endif
Daniel Veillard0ba59232002-02-10 13:20:39 +000019
20#ifdef HAVE_STDLIB_H
21#include <stdlib.h>
22#else
Owen Taylor3473f882001-02-23 17:55:21 +000023#ifdef HAVE_MALLOC_H
24#include <malloc.h>
25#endif
Owen Taylor3473f882001-02-23 17:55:21 +000026#endif
Daniel Veillard0ba59232002-02-10 13:20:39 +000027
Owen Taylor3473f882001-02-23 17:55:21 +000028#ifdef HAVE_CTYPE_H
29#include <ctype.h>
30#endif
31
Daniel Veillardf93a8662004-07-01 12:56:30 +000032/* #define DEBUG_MEMORY */
Daniel Veillard4432df22003-09-28 18:58:27 +000033
Daniel Veillard70cab352002-02-06 16:06:58 +000034/**
35 * MEM_LIST:
36 *
Daniel Veillard09459bf2008-07-30 12:58:11 +000037 * keep track of all allocated blocks for error reporting
Daniel Veillard70cab352002-02-06 16:06:58 +000038 * Always build the memory list !
39 */
Daniel Veillardc064b472003-09-29 10:55:05 +000040#ifdef DEBUG_MEMORY_LOCATION
Daniel Veillard70cab352002-02-06 16:06:58 +000041#ifndef MEM_LIST
42#define MEM_LIST /* keep a list of all the allocated memory blocks */
43#endif
Daniel Veillardc064b472003-09-29 10:55:05 +000044#endif
Owen Taylor3473f882001-02-23 17:55:21 +000045
William M. Brack5ab479b2004-06-10 13:00:15 +000046#include <libxml/globals.h> /* must come before xmlmemory.h */
Owen Taylor3473f882001-02-23 17:55:21 +000047#include <libxml/xmlmemory.h>
48#include <libxml/xmlerror.h>
William M. Brack0622fe82003-11-29 10:47:56 +000049#include <libxml/threads.h>
Owen Taylor3473f882001-02-23 17:55:21 +000050
Daniel Veillard4432df22003-09-28 18:58:27 +000051static int xmlMemInitialized = 0;
Daniel Veillardfb43bd62003-09-29 09:22:39 +000052static unsigned long debugMemSize = 0;
Daniel Veillard36e5cd52004-11-02 14:52:23 +000053static unsigned long debugMemBlocks = 0;
Daniel Veillardfb43bd62003-09-29 09:22:39 +000054static unsigned long debugMaxMemSize = 0;
William M. Brack0622fe82003-11-29 10:47:56 +000055static xmlMutexPtr xmlMemMutex = NULL;
Daniel Veillard4432df22003-09-28 18:58:27 +000056
Daniel Veillard56a4cb82001-03-24 17:00:36 +000057void xmlMallocBreakpoint(void);
Daniel Veillard56a4cb82001-03-24 17:00:36 +000058
59/************************************************************************
60 * *
Daniel Veillardf8e3db02012-09-11 13:26:36 +080061 * Macros, variables and associated types *
Daniel Veillard56a4cb82001-03-24 17:00:36 +000062 * *
63 ************************************************************************/
64
William M. Brack5ab479b2004-06-10 13:00:15 +000065#if !defined(LIBXML_THREAD_ENABLED) && !defined(LIBXML_THREAD_ALLOC_ENABLED)
Owen Taylor3473f882001-02-23 17:55:21 +000066#ifdef xmlMalloc
67#undef xmlMalloc
68#endif
69#ifdef xmlRealloc
70#undef xmlRealloc
71#endif
72#ifdef xmlMemStrdup
73#undef xmlMemStrdup
74#endif
William M. Brack5ab479b2004-06-10 13:00:15 +000075#endif
Owen Taylor3473f882001-02-23 17:55:21 +000076
77/*
78 * Each of the blocks allocated begin with a header containing informations
79 */
80
81#define MEMTAG 0x5aa5
82
83#define MALLOC_TYPE 1
84#define REALLOC_TYPE 2
85#define STRDUP_TYPE 3
Daniel Veillard3c908dc2003-04-19 00:07:51 +000086#define MALLOC_ATOMIC_TYPE 4
87#define REALLOC_ATOMIC_TYPE 5
Owen Taylor3473f882001-02-23 17:55:21 +000088
89typedef struct memnod {
90 unsigned int mh_tag;
91 unsigned int mh_type;
92 unsigned long mh_number;
93 size_t mh_size;
94#ifdef MEM_LIST
95 struct memnod *mh_next;
96 struct memnod *mh_prev;
97#endif
98 const char *mh_file;
99 unsigned int mh_line;
100} MEMHDR;
101
102
103#ifdef SUN4
104#define ALIGN_SIZE 16
105#else
106#define ALIGN_SIZE sizeof(double)
107#endif
108#define HDR_SIZE sizeof(MEMHDR)
109#define RESERVE_SIZE (((HDR_SIZE + (ALIGN_SIZE-1)) \
110 / ALIGN_SIZE ) * ALIGN_SIZE)
111
Xin Lia136fc22016-07-26 14:22:54 -0700112#define MAX_SIZE_T ((size_t)-1)
Owen Taylor3473f882001-02-23 17:55:21 +0000113
akirilov20297912018-06-01 13:43:34 -0700114#define CLIENT_2_HDR(a) ((void *) (((char *) (a)) - RESERVE_SIZE))
Owen Taylor3473f882001-02-23 17:55:21 +0000115#define HDR_2_CLIENT(a) ((void *) (((char *) (a)) + RESERVE_SIZE))
116
117
William M. Brack0622fe82003-11-29 10:47:56 +0000118static unsigned int block=0;
119static unsigned int xmlMemStopAtBlock = 0;
Daniel Veillardb44025c2001-10-11 22:55:55 +0000120static void *xmlMemTraceBlockAt = NULL;
Owen Taylor3473f882001-02-23 17:55:21 +0000121#ifdef MEM_LIST
122static MEMHDR *memlist = NULL;
123#endif
124
Daniel Veillard01c13b52002-12-10 15:19:08 +0000125static void debugmem_tag_error(void *addr);
Owen Taylor3473f882001-02-23 17:55:21 +0000126#ifdef MEM_LIST
Daniel Veillard01c13b52002-12-10 15:19:08 +0000127static void debugmem_list_add(MEMHDR *);
128static void debugmem_list_delete(MEMHDR *);
Owen Taylor3473f882001-02-23 17:55:21 +0000129#endif
130#define Mem_Tag_Err(a) debugmem_tag_error(a);
131
132#ifndef TEST_POINT
133#define TEST_POINT
134#endif
135
136/**
137 * xmlMallocBreakpoint:
138 *
139 * Breakpoint to use in conjunction with xmlMemStopAtBlock. When the block
140 * number reaches the specified value this function is called. One need to add a breakpoint
141 * to it to get the context in which the given block is allocated.
142 */
143
144void
145xmlMallocBreakpoint(void) {
146 xmlGenericError(xmlGenericErrorContext,
147 "xmlMallocBreakpoint reached on block %d\n", xmlMemStopAtBlock);
148}
149
150/**
151 * xmlMallocLoc:
152 * @size: an int specifying the size in byte to allocate.
153 * @file: the file name or NULL
154 * @line: the line number
155 *
156 * a malloc() equivalent, with logging of the allocation info.
157 *
158 * Returns a pointer to the allocated area or NULL in case of lack of memory.
159 */
160
161void *
Daniel Veillard8599e702001-07-17 21:38:51 +0000162xmlMallocLoc(size_t size, const char * file, int line)
Owen Taylor3473f882001-02-23 17:55:21 +0000163{
164 MEMHDR *p;
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000165 void *ret;
Daniel Veillard09459bf2008-07-30 12:58:11 +0000166
Owen Taylor3473f882001-02-23 17:55:21 +0000167 if (!xmlMemInitialized) xmlInitMemory();
168#ifdef DEBUG_MEMORY
169 xmlGenericError(xmlGenericErrorContext,
170 "Malloc(%d)\n",size);
171#endif
172
173 TEST_POINT
Daniel Veillard09459bf2008-07-30 12:58:11 +0000174
akirilov20297912018-06-01 13:43:34 -0700175 if (size > (MAX_SIZE_T - RESERVE_SIZE)) {
176 xmlGenericError(xmlGenericErrorContext,
177 "xmlMallocLoc : Unsigned overflow\n");
178 xmlMemoryDump();
179 return(NULL);
180 }
181
Owen Taylor3473f882001-02-23 17:55:21 +0000182 p = (MEMHDR *) malloc(RESERVE_SIZE+size);
183
184 if (!p) {
185 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard26908ab2002-01-01 16:50:03 +0000186 "xmlMallocLoc : Out of free space\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000187 xmlMemoryDump();
188 return(NULL);
Daniel Veillard09459bf2008-07-30 12:58:11 +0000189 }
Owen Taylor3473f882001-02-23 17:55:21 +0000190 p->mh_tag = MEMTAG;
Owen Taylor3473f882001-02-23 17:55:21 +0000191 p->mh_size = size;
192 p->mh_type = MALLOC_TYPE;
193 p->mh_file = file;
194 p->mh_line = line;
William M. Brack0622fe82003-11-29 10:47:56 +0000195 xmlMutexLock(xmlMemMutex);
196 p->mh_number = ++block;
Owen Taylor3473f882001-02-23 17:55:21 +0000197 debugMemSize += size;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000198 debugMemBlocks++;
Owen Taylor3473f882001-02-23 17:55:21 +0000199 if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
200#ifdef MEM_LIST
201 debugmem_list_add(p);
202#endif
William M. Brack0622fe82003-11-29 10:47:56 +0000203 xmlMutexUnlock(xmlMemMutex);
Daniel Veillard09459bf2008-07-30 12:58:11 +0000204
Owen Taylor3473f882001-02-23 17:55:21 +0000205#ifdef DEBUG_MEMORY
206 xmlGenericError(xmlGenericErrorContext,
207 "Malloc(%d) Ok\n",size);
208#endif
Daniel Veillard09459bf2008-07-30 12:58:11 +0000209
William M. Brack0622fe82003-11-29 10:47:56 +0000210 if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint();
Owen Taylor3473f882001-02-23 17:55:21 +0000211
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000212 ret = HDR_2_CLIENT(p);
213
214 if (xmlMemTraceBlockAt == ret) {
215 xmlGenericError(xmlGenericErrorContext,
Stefan Kostecb5d5a2011-05-06 17:40:10 +0300216 "%p : Malloc(%lu) Ok\n", xmlMemTraceBlockAt,
217 (long unsigned)size);
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000218 xmlMallocBreakpoint();
219 }
220
Owen Taylor3473f882001-02-23 17:55:21 +0000221 TEST_POINT
222
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000223 return(ret);
Owen Taylor3473f882001-02-23 17:55:21 +0000224}
225
226/**
Daniel Veillard3c908dc2003-04-19 00:07:51 +0000227 * xmlMallocAtomicLoc:
Xin Lia136fc22016-07-26 14:22:54 -0700228 * @size: an unsigned int specifying the size in byte to allocate.
Daniel Veillard3c908dc2003-04-19 00:07:51 +0000229 * @file: the file name or NULL
230 * @line: the line number
231 *
232 * a malloc() equivalent, with logging of the allocation info.
233 *
234 * Returns a pointer to the allocated area or NULL in case of lack of memory.
235 */
236
237void *
238xmlMallocAtomicLoc(size_t size, const char * file, int line)
239{
240 MEMHDR *p;
241 void *ret;
Daniel Veillard09459bf2008-07-30 12:58:11 +0000242
Daniel Veillard3c908dc2003-04-19 00:07:51 +0000243 if (!xmlMemInitialized) xmlInitMemory();
244#ifdef DEBUG_MEMORY
245 xmlGenericError(xmlGenericErrorContext,
246 "Malloc(%d)\n",size);
247#endif
248
249 TEST_POINT
Daniel Veillard09459bf2008-07-30 12:58:11 +0000250
Xin Lia136fc22016-07-26 14:22:54 -0700251 if (size > (MAX_SIZE_T - RESERVE_SIZE)) {
252 xmlGenericError(xmlGenericErrorContext,
akirilov20297912018-06-01 13:43:34 -0700253 "xmlMallocAtomicLoc : Unsigned overflow\n");
Xin Lia136fc22016-07-26 14:22:54 -0700254 xmlMemoryDump();
255 return(NULL);
256 }
257
Daniel Veillard3c908dc2003-04-19 00:07:51 +0000258 p = (MEMHDR *) malloc(RESERVE_SIZE+size);
259
260 if (!p) {
261 xmlGenericError(xmlGenericErrorContext,
Xin Lia136fc22016-07-26 14:22:54 -0700262 "xmlMallocAtomicLoc : Out of free space\n");
Daniel Veillard3c908dc2003-04-19 00:07:51 +0000263 xmlMemoryDump();
264 return(NULL);
Daniel Veillard09459bf2008-07-30 12:58:11 +0000265 }
Daniel Veillard3c908dc2003-04-19 00:07:51 +0000266 p->mh_tag = MEMTAG;
Daniel Veillard3c908dc2003-04-19 00:07:51 +0000267 p->mh_size = size;
268 p->mh_type = MALLOC_ATOMIC_TYPE;
269 p->mh_file = file;
270 p->mh_line = line;
William M. Brack0622fe82003-11-29 10:47:56 +0000271 xmlMutexLock(xmlMemMutex);
272 p->mh_number = ++block;
Daniel Veillard3c908dc2003-04-19 00:07:51 +0000273 debugMemSize += size;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000274 debugMemBlocks++;
Daniel Veillard3c908dc2003-04-19 00:07:51 +0000275 if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
276#ifdef MEM_LIST
277 debugmem_list_add(p);
278#endif
William M. Brack0622fe82003-11-29 10:47:56 +0000279 xmlMutexUnlock(xmlMemMutex);
Daniel Veillard3c908dc2003-04-19 00:07:51 +0000280
281#ifdef DEBUG_MEMORY
282 xmlGenericError(xmlGenericErrorContext,
283 "Malloc(%d) Ok\n",size);
284#endif
Daniel Veillard09459bf2008-07-30 12:58:11 +0000285
William M. Brack0622fe82003-11-29 10:47:56 +0000286 if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint();
Daniel Veillard3c908dc2003-04-19 00:07:51 +0000287
288 ret = HDR_2_CLIENT(p);
289
290 if (xmlMemTraceBlockAt == ret) {
291 xmlGenericError(xmlGenericErrorContext,
Stefan Kostecb5d5a2011-05-06 17:40:10 +0300292 "%p : Malloc(%lu) Ok\n", xmlMemTraceBlockAt,
293 (long unsigned)size);
Daniel Veillard3c908dc2003-04-19 00:07:51 +0000294 xmlMallocBreakpoint();
295 }
296
297 TEST_POINT
298
299 return(ret);
300}
301/**
Owen Taylor3473f882001-02-23 17:55:21 +0000302 * xmlMemMalloc:
303 * @size: an int specifying the size in byte to allocate.
304 *
305 * a malloc() equivalent, with logging of the allocation info.
306 *
307 * Returns a pointer to the allocated area or NULL in case of lack of memory.
308 */
309
310void *
Daniel Veillard8599e702001-07-17 21:38:51 +0000311xmlMemMalloc(size_t size)
Owen Taylor3473f882001-02-23 17:55:21 +0000312{
313 return(xmlMallocLoc(size, "none", 0));
314}
315
316/**
317 * xmlReallocLoc:
318 * @ptr: the initial memory block pointer
319 * @size: an int specifying the size in byte to allocate.
320 * @file: the file name or NULL
321 * @line: the line number
322 *
323 * a realloc() equivalent, with logging of the allocation info.
324 *
325 * Returns a pointer to the allocated area or NULL in case of lack of memory.
326 */
327
328void *
Daniel Veillard8599e702001-07-17 21:38:51 +0000329xmlReallocLoc(void *ptr,size_t size, const char * file, int line)
Owen Taylor3473f882001-02-23 17:55:21 +0000330{
Yegor Yefremov74464452014-10-10 12:23:09 +0200331 MEMHDR *p, *tmp;
Owen Taylor3473f882001-02-23 17:55:21 +0000332 unsigned long number;
Daniel Veillard529233c2004-07-02 12:23:44 +0000333#ifdef DEBUG_MEMORY
334 size_t oldsize;
335#endif
Owen Taylor3473f882001-02-23 17:55:21 +0000336
Daniel Veillarda76fe5c2003-04-24 16:06:47 +0000337 if (ptr == NULL)
Aleksey Sanine9f08112004-01-22 22:20:31 +0000338 return(xmlMallocLoc(size, file, line));
339
340 if (!xmlMemInitialized) xmlInitMemory();
Owen Taylor3473f882001-02-23 17:55:21 +0000341 TEST_POINT
342
343 p = CLIENT_2_HDR(ptr);
344 number = p->mh_number;
Daniel Veillard18ffe202005-04-14 17:50:59 +0000345 if (xmlMemStopAtBlock == number) xmlMallocBreakpoint();
Owen Taylor3473f882001-02-23 17:55:21 +0000346 if (p->mh_tag != MEMTAG) {
347 Mem_Tag_Err(p);
348 goto error;
349 }
350 p->mh_tag = ~MEMTAG;
William M. Brack0622fe82003-11-29 10:47:56 +0000351 xmlMutexLock(xmlMemMutex);
Owen Taylor3473f882001-02-23 17:55:21 +0000352 debugMemSize -= p->mh_size;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000353 debugMemBlocks--;
Daniel Veillard529233c2004-07-02 12:23:44 +0000354#ifdef DEBUG_MEMORY
355 oldsize = p->mh_size;
356#endif
Owen Taylor3473f882001-02-23 17:55:21 +0000357#ifdef MEM_LIST
358 debugmem_list_delete(p);
359#endif
William M. Brack0622fe82003-11-29 10:47:56 +0000360 xmlMutexUnlock(xmlMemMutex);
Daniel Veillard09459bf2008-07-30 12:58:11 +0000361
akirilov20297912018-06-01 13:43:34 -0700362 if (size > (MAX_SIZE_T - RESERVE_SIZE)) {
363 xmlGenericError(xmlGenericErrorContext,
364 "xmlReallocLoc : Unsigned overflow\n");
365 xmlMemoryDump();
366 return(NULL);
367 }
368
Yegor Yefremov74464452014-10-10 12:23:09 +0200369 tmp = (MEMHDR *) realloc(p,RESERVE_SIZE+size);
370 if (!tmp) {
371 free(p);
Owen Taylor3473f882001-02-23 17:55:21 +0000372 goto error;
373 }
Yegor Yefremov74464452014-10-10 12:23:09 +0200374 p = tmp;
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000375 if (xmlMemTraceBlockAt == ptr) {
376 xmlGenericError(xmlGenericErrorContext,
Stefan Kostecb5d5a2011-05-06 17:40:10 +0300377 "%p : Realloced(%lu -> %lu) Ok\n",
378 xmlMemTraceBlockAt, (long unsigned)p->mh_size,
379 (long unsigned)size);
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000380 xmlMallocBreakpoint();
381 }
Owen Taylor3473f882001-02-23 17:55:21 +0000382 p->mh_tag = MEMTAG;
383 p->mh_number = number;
384 p->mh_type = REALLOC_TYPE;
385 p->mh_size = size;
386 p->mh_file = file;
387 p->mh_line = line;
William M. Brack0622fe82003-11-29 10:47:56 +0000388 xmlMutexLock(xmlMemMutex);
Owen Taylor3473f882001-02-23 17:55:21 +0000389 debugMemSize += size;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000390 debugMemBlocks++;
Owen Taylor3473f882001-02-23 17:55:21 +0000391 if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
392#ifdef MEM_LIST
393 debugmem_list_add(p);
394#endif
William M. Brack0622fe82003-11-29 10:47:56 +0000395 xmlMutexUnlock(xmlMemMutex);
Owen Taylor3473f882001-02-23 17:55:21 +0000396
397 TEST_POINT
398
Daniel Veillard529233c2004-07-02 12:23:44 +0000399#ifdef DEBUG_MEMORY
400 xmlGenericError(xmlGenericErrorContext,
401 "Realloced(%d to %d) Ok\n", oldsize, size);
402#endif
Owen Taylor3473f882001-02-23 17:55:21 +0000403 return(HDR_2_CLIENT(p));
Daniel Veillard09459bf2008-07-30 12:58:11 +0000404
405error:
Owen Taylor3473f882001-02-23 17:55:21 +0000406 return(NULL);
407}
408
409/**
410 * xmlMemRealloc:
411 * @ptr: the initial memory block pointer
412 * @size: an int specifying the size in byte to allocate.
413 *
414 * a realloc() equivalent, with logging of the allocation info.
415 *
416 * Returns a pointer to the allocated area or NULL in case of lack of memory.
417 */
418
419void *
Daniel Veillard8599e702001-07-17 21:38:51 +0000420xmlMemRealloc(void *ptr,size_t size) {
Owen Taylor3473f882001-02-23 17:55:21 +0000421 return(xmlReallocLoc(ptr, size, "none", 0));
422}
423
424/**
425 * xmlMemFree:
426 * @ptr: the memory block pointer
427 *
428 * a free() equivalent, with error checking.
429 */
430void
431xmlMemFree(void *ptr)
432{
433 MEMHDR *p;
Daniel Veillard92ad2102001-03-27 12:47:33 +0000434 char *target;
Daniel Veillard529233c2004-07-02 12:23:44 +0000435#ifdef DEBUG_MEMORY
436 size_t size;
437#endif
Owen Taylor3473f882001-02-23 17:55:21 +0000438
Daniel Veillard2a512da2007-10-30 20:24:40 +0000439 if (ptr == NULL)
440 return;
441
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000442 if (ptr == (void *) -1) {
443 xmlGenericError(xmlGenericErrorContext,
444 "trying to free pointer from freed area\n");
445 goto error;
446 }
447
448 if (xmlMemTraceBlockAt == ptr) {
449 xmlGenericError(xmlGenericErrorContext,
450 "%p : Freed()\n", xmlMemTraceBlockAt);
451 xmlMallocBreakpoint();
452 }
453
Owen Taylor3473f882001-02-23 17:55:21 +0000454 TEST_POINT
455
Daniel Veillard92ad2102001-03-27 12:47:33 +0000456 target = (char *) ptr;
457
Owen Taylor3473f882001-02-23 17:55:21 +0000458 p = CLIENT_2_HDR(ptr);
459 if (p->mh_tag != MEMTAG) {
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000460 Mem_Tag_Err(p);
461 goto error;
Owen Taylor3473f882001-02-23 17:55:21 +0000462 }
Daniel Veillard18ffe202005-04-14 17:50:59 +0000463 if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint();
Owen Taylor3473f882001-02-23 17:55:21 +0000464 p->mh_tag = ~MEMTAG;
Daniel Veillard92ad2102001-03-27 12:47:33 +0000465 memset(target, -1, p->mh_size);
William M. Brack0622fe82003-11-29 10:47:56 +0000466 xmlMutexLock(xmlMemMutex);
467 debugMemSize -= p->mh_size;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000468 debugMemBlocks--;
Daniel Veillard529233c2004-07-02 12:23:44 +0000469#ifdef DEBUG_MEMORY
470 size = p->mh_size;
471#endif
Owen Taylor3473f882001-02-23 17:55:21 +0000472#ifdef MEM_LIST
473 debugmem_list_delete(p);
474#endif
William M. Brack0622fe82003-11-29 10:47:56 +0000475 xmlMutexUnlock(xmlMemMutex);
476
Owen Taylor3473f882001-02-23 17:55:21 +0000477 free(p);
478
479 TEST_POINT
480
Daniel Veillard529233c2004-07-02 12:23:44 +0000481#ifdef DEBUG_MEMORY
482 xmlGenericError(xmlGenericErrorContext,
483 "Freed(%d) Ok\n", size);
484#endif
Daniel Veillard09459bf2008-07-30 12:58:11 +0000485
Owen Taylor3473f882001-02-23 17:55:21 +0000486 return;
Daniel Veillard09459bf2008-07-30 12:58:11 +0000487
488error:
Owen Taylor3473f882001-02-23 17:55:21 +0000489 xmlGenericError(xmlGenericErrorContext,
akirilov20297912018-06-01 13:43:34 -0700490 "xmlMemFree(%p) error\n", ptr);
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000491 xmlMallocBreakpoint();
Owen Taylor3473f882001-02-23 17:55:21 +0000492 return;
493}
494
495/**
496 * xmlMemStrdupLoc:
Daniel Veillard9d06d302002-01-22 18:15:52 +0000497 * @str: the initial string pointer
Owen Taylor3473f882001-02-23 17:55:21 +0000498 * @file: the file name or NULL
499 * @line: the line number
500 *
501 * a strdup() equivalent, with logging of the allocation info.
502 *
Daniel Veillard26908ab2002-01-01 16:50:03 +0000503 * Returns a pointer to the new string or NULL if allocation error occurred.
Owen Taylor3473f882001-02-23 17:55:21 +0000504 */
505
506char *
507xmlMemStrdupLoc(const char *str, const char *file, int line)
508{
509 char *s;
510 size_t size = strlen(str) + 1;
511 MEMHDR *p;
512
513 if (!xmlMemInitialized) xmlInitMemory();
514 TEST_POINT
515
akirilov20297912018-06-01 13:43:34 -0700516 if (size > (MAX_SIZE_T - RESERVE_SIZE)) {
517 xmlGenericError(xmlGenericErrorContext,
518 "xmlMemStrdupLoc : Unsigned overflow\n");
519 xmlMemoryDump();
520 return(NULL);
521 }
522
Owen Taylor3473f882001-02-23 17:55:21 +0000523 p = (MEMHDR *) malloc(RESERVE_SIZE+size);
524 if (!p) {
525 goto error;
526 }
527 p->mh_tag = MEMTAG;
Owen Taylor3473f882001-02-23 17:55:21 +0000528 p->mh_size = size;
529 p->mh_type = STRDUP_TYPE;
530 p->mh_file = file;
531 p->mh_line = line;
William M. Brack0622fe82003-11-29 10:47:56 +0000532 xmlMutexLock(xmlMemMutex);
533 p->mh_number = ++block;
Owen Taylor3473f882001-02-23 17:55:21 +0000534 debugMemSize += size;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000535 debugMemBlocks++;
Owen Taylor3473f882001-02-23 17:55:21 +0000536 if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
537#ifdef MEM_LIST
538 debugmem_list_add(p);
539#endif
William M. Brack0622fe82003-11-29 10:47:56 +0000540 xmlMutexUnlock(xmlMemMutex);
Daniel Veillard09459bf2008-07-30 12:58:11 +0000541
Owen Taylor3473f882001-02-23 17:55:21 +0000542 s = (char *) HDR_2_CLIENT(p);
Daniel Veillard09459bf2008-07-30 12:58:11 +0000543
William M. Brack0622fe82003-11-29 10:47:56 +0000544 if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint();
Owen Taylor3473f882001-02-23 17:55:21 +0000545
Gaurav Guptab8480ae2014-07-26 21:14:53 +0800546 strcpy(s,str);
Daniel Veillard09459bf2008-07-30 12:58:11 +0000547
Owen Taylor3473f882001-02-23 17:55:21 +0000548 TEST_POINT
549
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000550 if (xmlMemTraceBlockAt == s) {
551 xmlGenericError(xmlGenericErrorContext,
552 "%p : Strdup() Ok\n", xmlMemTraceBlockAt);
553 xmlMallocBreakpoint();
554 }
555
Owen Taylor3473f882001-02-23 17:55:21 +0000556 return(s);
557
558error:
559 return(NULL);
560}
561
562/**
563 * xmlMemoryStrdup:
Daniel Veillard01c13b52002-12-10 15:19:08 +0000564 * @str: the initial string pointer
Owen Taylor3473f882001-02-23 17:55:21 +0000565 *
566 * a strdup() equivalent, with logging of the allocation info.
567 *
Daniel Veillard26908ab2002-01-01 16:50:03 +0000568 * Returns a pointer to the new string or NULL if allocation error occurred.
Owen Taylor3473f882001-02-23 17:55:21 +0000569 */
570
571char *
572xmlMemoryStrdup(const char *str) {
573 return(xmlMemStrdupLoc(str, "none", 0));
574}
575
576/**
577 * xmlMemUsed:
578 *
Daniel Veillarda9b66d02002-12-11 14:23:49 +0000579 * Provides the amount of memory currently allocated
Owen Taylor3473f882001-02-23 17:55:21 +0000580 *
581 * Returns an int representing the amount of memory allocated.
582 */
583
584int
585xmlMemUsed(void) {
Martin von Gagern8985cde2015-04-13 16:32:14 +0800586 int res;
587
588 xmlMutexLock(xmlMemMutex);
589 res = debugMemSize;
590 xmlMutexUnlock(xmlMemMutex);
591 return(res);
Owen Taylor3473f882001-02-23 17:55:21 +0000592}
593
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000594/**
595 * xmlMemBlocks:
596 *
597 * Provides the number of memory areas currently allocated
598 *
599 * Returns an int representing the number of blocks
600 */
601
602int
603xmlMemBlocks(void) {
Martin von Gagern8985cde2015-04-13 16:32:14 +0800604 int res;
605
606 xmlMutexLock(xmlMemMutex);
607 res = debugMemBlocks;
608 xmlMutexUnlock(xmlMemMutex);
609 return(res);
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000610}
611
Owen Taylor3473f882001-02-23 17:55:21 +0000612#ifdef MEM_LIST
613/**
614 * xmlMemContentShow:
615 * @fp: a FILE descriptor used as the output file
616 * @p: a memory block header
617 *
618 * tries to show some content from the memory block
619 */
620
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000621static void
Owen Taylor3473f882001-02-23 17:55:21 +0000622xmlMemContentShow(FILE *fp, MEMHDR *p)
623{
Gaurav7966a762014-05-09 17:00:08 +0800624 int i,j,k,len;
625 const char *buf;
Owen Taylor3473f882001-02-23 17:55:21 +0000626
627 if (p == NULL) {
628 fprintf(fp, " NULL");
629 return;
630 }
Gaurav7966a762014-05-09 17:00:08 +0800631 len = p->mh_size;
632 buf = (const char *) HDR_2_CLIENT(p);
Owen Taylor3473f882001-02-23 17:55:21 +0000633
634 for (i = 0;i < len;i++) {
635 if (buf[i] == 0) break;
Daniel Veillard9f28f302002-02-15 20:48:08 +0000636 if (!isprint((unsigned char) buf[i])) break;
Owen Taylor3473f882001-02-23 17:55:21 +0000637 }
638 if ((i < 4) && ((buf[i] != 0) || (i == 0))) {
639 if (len >= 4) {
640 MEMHDR *q;
641 void *cur;
642
Daniel Veillardf4721d62006-10-11 21:12:10 +0000643 for (j = 0;(j < len -3) && (j < 40);j += 4) {
Owen Taylor3473f882001-02-23 17:55:21 +0000644 cur = *((void **) &buf[j]);
645 q = CLIENT_2_HDR(cur);
646 p = memlist;
Daniel Veillardf4721d62006-10-11 21:12:10 +0000647 k = 0;
Owen Taylor3473f882001-02-23 17:55:21 +0000648 while (p != NULL) {
649 if (p == q) break;
650 p = p->mh_next;
Daniel Veillardf4721d62006-10-11 21:12:10 +0000651 if (k++ > 100) break;
Owen Taylor3473f882001-02-23 17:55:21 +0000652 }
653 if ((p != NULL) && (p == q)) {
654 fprintf(fp, " pointer to #%lu at index %d",
655 p->mh_number, j);
656 return;
657 }
658 }
659 }
660 } else if ((i == 0) && (buf[i] == 0)) {
661 fprintf(fp," null");
662 } else {
Daniel Veillard09459bf2008-07-30 12:58:11 +0000663 if (buf[i] == 0) fprintf(fp," \"%.25s\"", buf);
Owen Taylor3473f882001-02-23 17:55:21 +0000664 else {
665 fprintf(fp," [");
666 for (j = 0;j < i;j++)
667 fprintf(fp,"%c", buf[j]);
668 fprintf(fp,"]");
669 }
670 }
671}
672#endif
673
674/**
Daniel Veillard09459bf2008-07-30 12:58:11 +0000675 * xmlMemDisplayLast:
676 * @fp: a FILE descriptor used as the output file, if NULL, the result is
677 * written to the file .memorylist
678 * @nbBytes: the amount of memory to dump
679 *
680 * the last nbBytes of memory allocated and not freed, useful for dumping
681 * the memory left allocated between two places at runtime.
682 */
683
684void
685xmlMemDisplayLast(FILE *fp, long nbBytes)
686{
687#ifdef MEM_LIST
688 MEMHDR *p;
689 unsigned idx;
690 int nb = 0;
691#endif
692 FILE *old_fp = fp;
693
694 if (nbBytes <= 0)
695 return;
696
697 if (fp == NULL) {
698 fp = fopen(".memorylist", "w");
699 if (fp == NULL)
700 return;
701 }
702
703#ifdef MEM_LIST
704 fprintf(fp," Last %li MEMORY ALLOCATED : %lu, MAX was %lu\n",
705 nbBytes, debugMemSize, debugMaxMemSize);
706 fprintf(fp,"BLOCK NUMBER SIZE TYPE\n");
707 idx = 0;
708 xmlMutexLock(xmlMemMutex);
709 p = memlist;
710 while ((p) && (nbBytes > 0)) {
711 fprintf(fp,"%-5u %6lu %6lu ",idx++,p->mh_number,
712 (unsigned long)p->mh_size);
713 switch (p->mh_type) {
714 case STRDUP_TYPE:fprintf(fp,"strdup() in ");break;
715 case MALLOC_TYPE:fprintf(fp,"malloc() in ");break;
716 case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
717 case MALLOC_ATOMIC_TYPE:fprintf(fp,"atomicmalloc() in ");break;
718 case REALLOC_ATOMIC_TYPE:fprintf(fp,"atomicrealloc() in ");break;
719 default:
720 fprintf(fp,"Unknown memory block, may be corrupted");
721 xmlMutexUnlock(xmlMemMutex);
722 if (old_fp == NULL)
723 fclose(fp);
724 return;
725 }
726 if (p->mh_file != NULL) fprintf(fp,"%s(%u)", p->mh_file, p->mh_line);
727 if (p->mh_tag != MEMTAG)
728 fprintf(fp," INVALID");
729 nb++;
730 if (nb < 100)
731 xmlMemContentShow(fp, p);
732 else
733 fprintf(fp," skip");
734
735 fprintf(fp,"\n");
736 nbBytes -= (unsigned long)p->mh_size;
737 p = p->mh_next;
738 }
739 xmlMutexUnlock(xmlMemMutex);
740#else
741 fprintf(fp,"Memory list not compiled (MEM_LIST not defined !)\n");
742#endif
743 if (old_fp == NULL)
744 fclose(fp);
745}
746
747/**
Owen Taylor3473f882001-02-23 17:55:21 +0000748 * xmlMemDisplay:
749 * @fp: a FILE descriptor used as the output file, if NULL, the result is
750 * written to the file .memorylist
751 *
752 * show in-extenso the memory blocks allocated
753 */
754
755void
756xmlMemDisplay(FILE *fp)
757{
758#ifdef MEM_LIST
759 MEMHDR *p;
Daniel Veillard144024e2002-02-13 21:14:46 +0000760 unsigned idx;
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000761 int nb = 0;
Owen Taylor3473f882001-02-23 17:55:21 +0000762#if defined(HAVE_LOCALTIME) && defined(HAVE_STRFTIME)
763 time_t currentTime;
764 char buf[500];
765 struct tm * tstruct;
Daniel Veillard942d6c72005-05-08 11:39:56 +0000766#endif
767#endif
768 FILE *old_fp = fp;
Owen Taylor3473f882001-02-23 17:55:21 +0000769
Daniel Veillard942d6c72005-05-08 11:39:56 +0000770 if (fp == NULL) {
771 fp = fopen(".memorylist", "w");
772 if (fp == NULL)
773 return;
774 }
775
776#ifdef MEM_LIST
777#if defined(HAVE_LOCALTIME) && defined(HAVE_STRFTIME)
Owen Taylor3473f882001-02-23 17:55:21 +0000778 currentTime = time(NULL);
779 tstruct = localtime(&currentTime);
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000780 strftime(buf, sizeof(buf) - 1, "%I:%M:%S %p", tstruct);
Owen Taylor3473f882001-02-23 17:55:21 +0000781 fprintf(fp," %s\n\n", buf);
782#endif
783
Daniel Veillard09459bf2008-07-30 12:58:11 +0000784
Owen Taylor3473f882001-02-23 17:55:21 +0000785 fprintf(fp," MEMORY ALLOCATED : %lu, MAX was %lu\n",
786 debugMemSize, debugMaxMemSize);
787 fprintf(fp,"BLOCK NUMBER SIZE TYPE\n");
788 idx = 0;
William M. Brack0622fe82003-11-29 10:47:56 +0000789 xmlMutexLock(xmlMemMutex);
Owen Taylor3473f882001-02-23 17:55:21 +0000790 p = memlist;
791 while (p) {
Daniel Veillard144024e2002-02-13 21:14:46 +0000792 fprintf(fp,"%-5u %6lu %6lu ",idx++,p->mh_number,
793 (unsigned long)p->mh_size);
Owen Taylor3473f882001-02-23 17:55:21 +0000794 switch (p->mh_type) {
795 case STRDUP_TYPE:fprintf(fp,"strdup() in ");break;
796 case MALLOC_TYPE:fprintf(fp,"malloc() in ");break;
Daniel Veillard529233c2004-07-02 12:23:44 +0000797 case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
Daniel Veillard3c908dc2003-04-19 00:07:51 +0000798 case MALLOC_ATOMIC_TYPE:fprintf(fp,"atomicmalloc() in ");break;
Daniel Veillard529233c2004-07-02 12:23:44 +0000799 case REALLOC_ATOMIC_TYPE:fprintf(fp,"atomicrealloc() in ");break;
800 default:
William M. Brack13dfa872004-09-18 04:52:08 +0000801 fprintf(fp,"Unknown memory block, may be corrupted");
Daniel Veillard529233c2004-07-02 12:23:44 +0000802 xmlMutexUnlock(xmlMemMutex);
Daniel Veillard942d6c72005-05-08 11:39:56 +0000803 if (old_fp == NULL)
804 fclose(fp);
Daniel Veillard529233c2004-07-02 12:23:44 +0000805 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000806 }
William M. Brack13dfa872004-09-18 04:52:08 +0000807 if (p->mh_file != NULL) fprintf(fp,"%s(%u)", p->mh_file, p->mh_line);
Owen Taylor3473f882001-02-23 17:55:21 +0000808 if (p->mh_tag != MEMTAG)
809 fprintf(fp," INVALID");
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000810 nb++;
811 if (nb < 100)
812 xmlMemContentShow(fp, p);
813 else
814 fprintf(fp," skip");
815
Owen Taylor3473f882001-02-23 17:55:21 +0000816 fprintf(fp,"\n");
817 p = p->mh_next;
818 }
William M. Brack0622fe82003-11-29 10:47:56 +0000819 xmlMutexUnlock(xmlMemMutex);
Owen Taylor3473f882001-02-23 17:55:21 +0000820#else
821 fprintf(fp,"Memory list not compiled (MEM_LIST not defined !)\n");
822#endif
Daniel Veillard942d6c72005-05-08 11:39:56 +0000823 if (old_fp == NULL)
824 fclose(fp);
Owen Taylor3473f882001-02-23 17:55:21 +0000825}
826
827#ifdef MEM_LIST
828
Daniel Veillard01c13b52002-12-10 15:19:08 +0000829static void debugmem_list_add(MEMHDR *p)
Owen Taylor3473f882001-02-23 17:55:21 +0000830{
831 p->mh_next = memlist;
832 p->mh_prev = NULL;
833 if (memlist) memlist->mh_prev = p;
834 memlist = p;
835#ifdef MEM_LIST_DEBUG
836 if (stderr)
837 Mem_Display(stderr);
838#endif
839}
840
Daniel Veillard01c13b52002-12-10 15:19:08 +0000841static void debugmem_list_delete(MEMHDR *p)
Owen Taylor3473f882001-02-23 17:55:21 +0000842{
843 if (p->mh_next)
844 p->mh_next->mh_prev = p->mh_prev;
845 if (p->mh_prev)
846 p->mh_prev->mh_next = p->mh_next;
847 else memlist = p->mh_next;
848#ifdef MEM_LIST_DEBUG
849 if (stderr)
850 Mem_Display(stderr);
851#endif
852}
853
854#endif
855
856/*
Daniel Veillard01c13b52002-12-10 15:19:08 +0000857 * debugmem_tag_error:
858 *
859 * internal error function.
Owen Taylor3473f882001-02-23 17:55:21 +0000860 */
Daniel Veillard09459bf2008-07-30 12:58:11 +0000861
Daniel Veillard01c13b52002-12-10 15:19:08 +0000862static void debugmem_tag_error(void *p)
Owen Taylor3473f882001-02-23 17:55:21 +0000863{
864 xmlGenericError(xmlGenericErrorContext,
865 "Memory tag error occurs :%p \n\t bye\n", p);
866#ifdef MEM_LIST
867 if (stderr)
868 xmlMemDisplay(stderr);
869#endif
870}
871
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000872#ifdef MEM_LIST
Daniel Veillardb44025c2001-10-11 22:55:55 +0000873static FILE *xmlMemoryDumpFile = NULL;
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000874#endif
Owen Taylor3473f882001-02-23 17:55:21 +0000875
Owen Taylor3473f882001-02-23 17:55:21 +0000876/**
Daniel Veillardfb43bd62003-09-29 09:22:39 +0000877 * xmlMemShow:
878 * @fp: a FILE descriptor used as the output file
879 * @nr: number of entries to dump
880 *
881 * show a show display of the memory allocated, and dump
882 * the @nr last allocated areas which were not freed
883 */
884
885void
Daniel Veillardc064b472003-09-29 10:55:05 +0000886xmlMemShow(FILE *fp, int nr ATTRIBUTE_UNUSED)
Daniel Veillardfb43bd62003-09-29 09:22:39 +0000887{
Daniel Veillardfb43bd62003-09-29 09:22:39 +0000888#ifdef MEM_LIST
889 MEMHDR *p;
890#endif
Daniel Veillardfb43bd62003-09-29 09:22:39 +0000891
892 if (fp != NULL)
893 fprintf(fp," MEMORY ALLOCATED : %lu, MAX was %lu\n",
894 debugMemSize, debugMaxMemSize);
Daniel Veillardfb43bd62003-09-29 09:22:39 +0000895#ifdef MEM_LIST
William M. Brack0622fe82003-11-29 10:47:56 +0000896 xmlMutexLock(xmlMemMutex);
Daniel Veillardfb43bd62003-09-29 09:22:39 +0000897 if (nr > 0) {
898 fprintf(fp,"NUMBER SIZE TYPE WHERE\n");
899 p = memlist;
900 while ((p) && nr > 0) {
901 fprintf(fp,"%6lu %6lu ",p->mh_number,(unsigned long)p->mh_size);
902 switch (p->mh_type) {
903 case STRDUP_TYPE:fprintf(fp,"strdup() in ");break;
904 case MALLOC_TYPE:fprintf(fp,"malloc() in ");break;
905 case MALLOC_ATOMIC_TYPE:fprintf(fp,"atomicmalloc() in ");break;
906 case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
907 case REALLOC_ATOMIC_TYPE:fprintf(fp,"atomicrealloc() in ");break;
908 default:fprintf(fp," ??? in ");break;
909 }
910 if (p->mh_file != NULL)
William M. Brack13dfa872004-09-18 04:52:08 +0000911 fprintf(fp,"%s(%u)", p->mh_file, p->mh_line);
Daniel Veillardfb43bd62003-09-29 09:22:39 +0000912 if (p->mh_tag != MEMTAG)
913 fprintf(fp," INVALID");
914 xmlMemContentShow(fp, p);
915 fprintf(fp,"\n");
916 nr--;
917 p = p->mh_next;
918 }
919 }
William M. Brack0622fe82003-11-29 10:47:56 +0000920 xmlMutexUnlock(xmlMemMutex);
Daniel Veillard09459bf2008-07-30 12:58:11 +0000921#endif /* MEM_LIST */
Daniel Veillardfb43bd62003-09-29 09:22:39 +0000922}
923
924/**
Owen Taylor3473f882001-02-23 17:55:21 +0000925 * xmlMemoryDump:
926 *
927 * Dump in-extenso the memory blocks allocated to the file .memorylist
928 */
929
930void
931xmlMemoryDump(void)
932{
Daniel Veillardc064b472003-09-29 10:55:05 +0000933#ifdef MEM_LIST
Owen Taylor3473f882001-02-23 17:55:21 +0000934 FILE *dump;
935
Daniel Veillard5997aca2002-03-18 18:36:20 +0000936 if (debugMaxMemSize == 0)
937 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000938 dump = fopen(".memdump", "w");
Daniel Veillardcd337f02001-11-22 18:20:37 +0000939 if (dump == NULL)
940 xmlMemoryDumpFile = stderr;
Owen Taylor3473f882001-02-23 17:55:21 +0000941 else xmlMemoryDumpFile = dump;
942
943 xmlMemDisplay(xmlMemoryDumpFile);
944
945 if (dump != NULL) fclose(dump);
Daniel Veillardc064b472003-09-29 10:55:05 +0000946#endif /* MEM_LIST */
Owen Taylor3473f882001-02-23 17:55:21 +0000947}
948
949
950/****************************************************************
951 * *
952 * Initialization Routines *
953 * *
954 ****************************************************************/
955
Owen Taylor3473f882001-02-23 17:55:21 +0000956/**
957 * xmlInitMemory:
958 *
959 * Initialize the memory layer.
960 *
961 * Returns 0 on success
962 */
Owen Taylor3473f882001-02-23 17:55:21 +0000963int
964xmlInitMemory(void)
965{
Daniel Veillarde15df582004-07-13 15:25:08 +0000966#ifdef HAVE_STDLIB_H
967 char *breakpoint;
Daniel Veillard09459bf2008-07-30 12:58:11 +0000968#endif
Daniel Veillardf93a8662004-07-01 12:56:30 +0000969#ifdef DEBUG_MEMORY
970 xmlGenericError(xmlGenericErrorContext,
971 "xmlInitMemory()\n");
Daniel Veillard09459bf2008-07-30 12:58:11 +0000972#endif
William M. Brack92029422004-01-04 01:01:14 +0000973 /*
974 This is really not good code (see Bug 130419). Suggestions for
975 improvement will be welcome!
976 */
977 if (xmlMemInitialized) return(-1);
William M. Brack0622fe82003-11-29 10:47:56 +0000978 xmlMemInitialized = 1;
William M. Brack0622fe82003-11-29 10:47:56 +0000979 xmlMemMutex = xmlNewMutex();
Owen Taylor3473f882001-02-23 17:55:21 +0000980
981#ifdef HAVE_STDLIB_H
982 breakpoint = getenv("XML_MEM_BREAKPOINT");
983 if (breakpoint != NULL) {
William M. Brack0622fe82003-11-29 10:47:56 +0000984 sscanf(breakpoint, "%ud", &xmlMemStopAtBlock);
Owen Taylor3473f882001-02-23 17:55:21 +0000985 }
Daniel Veillard09459bf2008-07-30 12:58:11 +0000986#endif
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000987#ifdef HAVE_STDLIB_H
988 breakpoint = getenv("XML_MEM_TRACE");
989 if (breakpoint != NULL) {
990 sscanf(breakpoint, "%p", &xmlMemTraceBlockAt);
991 }
Daniel Veillard09459bf2008-07-30 12:58:11 +0000992#endif
993
Owen Taylor3473f882001-02-23 17:55:21 +0000994#ifdef DEBUG_MEMORY
995 xmlGenericError(xmlGenericErrorContext,
996 "xmlInitMemory() Ok\n");
Daniel Veillard09459bf2008-07-30 12:58:11 +0000997#endif
Daniel Veillard4432df22003-09-28 18:58:27 +0000998 return(0);
Owen Taylor3473f882001-02-23 17:55:21 +0000999}
1000
1001/**
William M. Brack72ee48d2003-12-30 08:30:19 +00001002 * xmlCleanupMemory:
1003 *
Daniel Veillard91b955c2004-12-10 10:26:42 +00001004 * Free up all the memory allocated by the library for its own
1005 * use. This should not be called by user level code.
William M. Brack72ee48d2003-12-30 08:30:19 +00001006 */
1007void
1008xmlCleanupMemory(void) {
Daniel Veillardf93a8662004-07-01 12:56:30 +00001009#ifdef DEBUG_MEMORY
1010 xmlGenericError(xmlGenericErrorContext,
1011 "xmlCleanupMemory()\n");
Daniel Veillard09459bf2008-07-30 12:58:11 +00001012#endif
William M. Brack72ee48d2003-12-30 08:30:19 +00001013 if (xmlMemInitialized == 0)
1014 return;
1015
1016 xmlFreeMutex(xmlMemMutex);
Daniel Veillard1a9b7082004-01-02 10:42:01 +00001017 xmlMemMutex = NULL;
William M. Brack72ee48d2003-12-30 08:30:19 +00001018 xmlMemInitialized = 0;
Daniel Veillardf93a8662004-07-01 12:56:30 +00001019#ifdef DEBUG_MEMORY
1020 xmlGenericError(xmlGenericErrorContext,
1021 "xmlCleanupMemory() Ok\n");
Daniel Veillard09459bf2008-07-30 12:58:11 +00001022#endif
William M. Brack72ee48d2003-12-30 08:30:19 +00001023}
1024
1025/**
Owen Taylor3473f882001-02-23 17:55:21 +00001026 * xmlMemSetup:
1027 * @freeFunc: the free() function to use
1028 * @mallocFunc: the malloc() function to use
1029 * @reallocFunc: the realloc() function to use
1030 * @strdupFunc: the strdup() function to use
1031 *
1032 * Override the default memory access functions with a new set
1033 * This has to be called before any other libxml routines !
1034 *
1035 * Should this be blocked if there was already some allocations
1036 * done ?
1037 *
1038 * Returns 0 on success
1039 */
1040int
1041xmlMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc,
1042 xmlReallocFunc reallocFunc, xmlStrdupFunc strdupFunc) {
Daniel Veillardf93a8662004-07-01 12:56:30 +00001043#ifdef DEBUG_MEMORY
1044 xmlGenericError(xmlGenericErrorContext,
1045 "xmlMemSetup()\n");
Daniel Veillard09459bf2008-07-30 12:58:11 +00001046#endif
Owen Taylor3473f882001-02-23 17:55:21 +00001047 if (freeFunc == NULL)
1048 return(-1);
1049 if (mallocFunc == NULL)
1050 return(-1);
1051 if (reallocFunc == NULL)
1052 return(-1);
1053 if (strdupFunc == NULL)
1054 return(-1);
1055 xmlFree = freeFunc;
1056 xmlMalloc = mallocFunc;
Daniel Veillard3c908dc2003-04-19 00:07:51 +00001057 xmlMallocAtomic = mallocFunc;
Owen Taylor3473f882001-02-23 17:55:21 +00001058 xmlRealloc = reallocFunc;
1059 xmlMemStrdup = strdupFunc;
Daniel Veillardf93a8662004-07-01 12:56:30 +00001060#ifdef DEBUG_MEMORY
1061 xmlGenericError(xmlGenericErrorContext,
1062 "xmlMemSetup() Ok\n");
Daniel Veillard09459bf2008-07-30 12:58:11 +00001063#endif
Owen Taylor3473f882001-02-23 17:55:21 +00001064 return(0);
1065}
1066
1067/**
1068 * xmlMemGet:
Daniel Veillarda9b66d02002-12-11 14:23:49 +00001069 * @freeFunc: place to save the free() function in use
1070 * @mallocFunc: place to save the malloc() function in use
1071 * @reallocFunc: place to save the realloc() function in use
1072 * @strdupFunc: place to save the strdup() function in use
Owen Taylor3473f882001-02-23 17:55:21 +00001073 *
Daniel Veillarda9b66d02002-12-11 14:23:49 +00001074 * Provides the memory access functions set currently in use
Owen Taylor3473f882001-02-23 17:55:21 +00001075 *
1076 * Returns 0 on success
1077 */
1078int
1079xmlMemGet(xmlFreeFunc *freeFunc, xmlMallocFunc *mallocFunc,
1080 xmlReallocFunc *reallocFunc, xmlStrdupFunc *strdupFunc) {
1081 if (freeFunc != NULL) *freeFunc = xmlFree;
1082 if (mallocFunc != NULL) *mallocFunc = xmlMalloc;
1083 if (reallocFunc != NULL) *reallocFunc = xmlRealloc;
1084 if (strdupFunc != NULL) *strdupFunc = xmlMemStrdup;
1085 return(0);
1086}
1087
Daniel Veillard3c908dc2003-04-19 00:07:51 +00001088/**
1089 * xmlGcMemSetup:
1090 * @freeFunc: the free() function to use
1091 * @mallocFunc: the malloc() function to use
1092 * @mallocAtomicFunc: the malloc() function to use for atomic allocations
1093 * @reallocFunc: the realloc() function to use
1094 * @strdupFunc: the strdup() function to use
1095 *
1096 * Override the default memory access functions with a new set
1097 * This has to be called before any other libxml routines !
1098 * The mallocAtomicFunc is specialized for atomic block
1099 * allocations (i.e. of areas useful for garbage collected memory allocators
1100 *
1101 * Should this be blocked if there was already some allocations
1102 * done ?
1103 *
1104 * Returns 0 on success
1105 */
1106int
1107xmlGcMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc,
1108 xmlMallocFunc mallocAtomicFunc, xmlReallocFunc reallocFunc,
1109 xmlStrdupFunc strdupFunc) {
Daniel Veillardf93a8662004-07-01 12:56:30 +00001110#ifdef DEBUG_MEMORY
1111 xmlGenericError(xmlGenericErrorContext,
1112 "xmlGcMemSetup()\n");
Daniel Veillard09459bf2008-07-30 12:58:11 +00001113#endif
Daniel Veillard3c908dc2003-04-19 00:07:51 +00001114 if (freeFunc == NULL)
1115 return(-1);
1116 if (mallocFunc == NULL)
1117 return(-1);
1118 if (mallocAtomicFunc == NULL)
1119 return(-1);
1120 if (reallocFunc == NULL)
1121 return(-1);
1122 if (strdupFunc == NULL)
1123 return(-1);
1124 xmlFree = freeFunc;
1125 xmlMalloc = mallocFunc;
1126 xmlMallocAtomic = mallocAtomicFunc;
1127 xmlRealloc = reallocFunc;
1128 xmlMemStrdup = strdupFunc;
Daniel Veillardf93a8662004-07-01 12:56:30 +00001129#ifdef DEBUG_MEMORY
1130 xmlGenericError(xmlGenericErrorContext,
1131 "xmlGcMemSetup() Ok\n");
Daniel Veillard09459bf2008-07-30 12:58:11 +00001132#endif
Daniel Veillard3c908dc2003-04-19 00:07:51 +00001133 return(0);
1134}
1135
1136/**
1137 * xmlGcMemGet:
1138 * @freeFunc: place to save the free() function in use
1139 * @mallocFunc: place to save the malloc() function in use
1140 * @mallocAtomicFunc: place to save the atomic malloc() function in use
1141 * @reallocFunc: place to save the realloc() function in use
1142 * @strdupFunc: place to save the strdup() function in use
1143 *
1144 * Provides the memory access functions set currently in use
1145 * The mallocAtomicFunc is specialized for atomic block
1146 * allocations (i.e. of areas useful for garbage collected memory allocators
1147 *
1148 * Returns 0 on success
1149 */
1150int
1151xmlGcMemGet(xmlFreeFunc *freeFunc, xmlMallocFunc *mallocFunc,
1152 xmlMallocFunc *mallocAtomicFunc, xmlReallocFunc *reallocFunc,
1153 xmlStrdupFunc *strdupFunc) {
1154 if (freeFunc != NULL) *freeFunc = xmlFree;
1155 if (mallocFunc != NULL) *mallocFunc = xmlMalloc;
1156 if (mallocAtomicFunc != NULL) *mallocAtomicFunc = xmlMallocAtomic;
1157 if (reallocFunc != NULL) *reallocFunc = xmlRealloc;
1158 if (strdupFunc != NULL) *strdupFunc = xmlMemStrdup;
1159 return(0);
1160}
1161
Daniel Veillard5d4644e2005-04-01 13:11:58 +00001162#define bottom_xmlmemory
1163#include "elfgcchack.h"