Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/xml2/xmlmemory.c
4393 views
1
/*
2
* xmlmemory.c: libxml memory allocator wrapper.
3
*
4
* [email protected]
5
*/
6
7
#define IN_LIBXML
8
#include "libxml.h"
9
10
#include <string.h>
11
#include <stdlib.h>
12
#include <ctype.h>
13
#include <time.h>
14
15
/**
16
* MEM_LIST:
17
*
18
* keep track of all allocated blocks for error reporting
19
* Always build the memory list !
20
*/
21
#ifdef DEBUG_MEMORY_LOCATION
22
#ifndef MEM_LIST
23
#define MEM_LIST /* keep a list of all the allocated memory blocks */
24
#endif
25
#endif
26
27
#include <libxml/xmlmemory.h>
28
#include <libxml/xmlerror.h>
29
#include <libxml/parser.h>
30
#include <libxml/threads.h>
31
32
#include "private/memory.h"
33
#include "private/threads.h"
34
35
static unsigned long debugMemSize = 0;
36
static unsigned long debugMemBlocks = 0;
37
static unsigned long debugMaxMemSize = 0;
38
static xmlMutex xmlMemMutex;
39
40
void xmlMallocBreakpoint(void);
41
42
/************************************************************************
43
* *
44
* Macros, variables and associated types *
45
* *
46
************************************************************************/
47
48
#if !defined(LIBXML_THREAD_ENABLED) && !defined(LIBXML_THREAD_ALLOC_ENABLED)
49
#ifdef xmlMalloc
50
#undef xmlMalloc
51
#endif
52
#ifdef xmlRealloc
53
#undef xmlRealloc
54
#endif
55
#ifdef xmlMemStrdup
56
#undef xmlMemStrdup
57
#endif
58
#endif
59
60
/*
61
* Each of the blocks allocated begin with a header containing information
62
*/
63
64
#define MEMTAG 0x5aa5U
65
66
#define MALLOC_TYPE 1
67
#define REALLOC_TYPE 2
68
#define STRDUP_TYPE 3
69
#define MALLOC_ATOMIC_TYPE 4
70
#define REALLOC_ATOMIC_TYPE 5
71
72
typedef struct memnod {
73
unsigned int mh_tag;
74
unsigned int mh_type;
75
unsigned long mh_number;
76
size_t mh_size;
77
#ifdef MEM_LIST
78
struct memnod *mh_next;
79
struct memnod *mh_prev;
80
#endif
81
const char *mh_file;
82
unsigned int mh_line;
83
} MEMHDR;
84
85
86
#ifdef SUN4
87
#define ALIGN_SIZE 16
88
#else
89
#define ALIGN_SIZE sizeof(double)
90
#endif
91
#define HDR_SIZE sizeof(MEMHDR)
92
#define RESERVE_SIZE (((HDR_SIZE + (ALIGN_SIZE-1)) \
93
/ ALIGN_SIZE ) * ALIGN_SIZE)
94
95
#define MAX_SIZE_T ((size_t)-1)
96
97
#define CLIENT_2_HDR(a) ((void *) (((char *) (a)) - RESERVE_SIZE))
98
#define HDR_2_CLIENT(a) ((void *) (((char *) (a)) + RESERVE_SIZE))
99
100
101
static unsigned int block=0;
102
static unsigned int xmlMemStopAtBlock = 0;
103
static void *xmlMemTraceBlockAt = NULL;
104
#ifdef MEM_LIST
105
static MEMHDR *memlist = NULL;
106
#endif
107
108
static void debugmem_tag_error(void *addr);
109
#ifdef MEM_LIST
110
static void debugmem_list_add(MEMHDR *);
111
static void debugmem_list_delete(MEMHDR *);
112
#endif
113
#define Mem_Tag_Err(a) debugmem_tag_error(a);
114
115
#ifndef TEST_POINT
116
#define TEST_POINT
117
#endif
118
119
/**
120
* xmlMallocBreakpoint:
121
*
122
* Breakpoint to use in conjunction with xmlMemStopAtBlock. When the block
123
* number reaches the specified value this function is called. One need to add a breakpoint
124
* to it to get the context in which the given block is allocated.
125
*/
126
127
void
128
xmlMallocBreakpoint(void) {
129
xmlGenericError(xmlGenericErrorContext,
130
"xmlMallocBreakpoint reached on block %d\n", xmlMemStopAtBlock);
131
}
132
133
/**
134
* xmlMallocLoc:
135
* @size: an int specifying the size in byte to allocate.
136
* @file: the file name or NULL
137
* @line: the line number
138
*
139
* a malloc() equivalent, with logging of the allocation info.
140
*
141
* Returns a pointer to the allocated area or NULL in case of lack of memory.
142
*/
143
144
void *
145
xmlMallocLoc(size_t size, const char * file, int line)
146
{
147
MEMHDR *p;
148
void *ret;
149
150
xmlInitParser();
151
152
TEST_POINT
153
154
if (size > (MAX_SIZE_T - RESERVE_SIZE)) {
155
xmlGenericError(xmlGenericErrorContext,
156
"xmlMallocLoc : Unsigned overflow\n");
157
return(NULL);
158
}
159
160
p = (MEMHDR *) malloc(RESERVE_SIZE+size);
161
162
if (!p) {
163
xmlGenericError(xmlGenericErrorContext,
164
"xmlMallocLoc : Out of free space\n");
165
return(NULL);
166
}
167
p->mh_tag = MEMTAG;
168
p->mh_size = size;
169
p->mh_type = MALLOC_TYPE;
170
p->mh_file = file;
171
p->mh_line = line;
172
xmlMutexLock(&xmlMemMutex);
173
p->mh_number = ++block;
174
debugMemSize += size;
175
debugMemBlocks++;
176
if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
177
#ifdef MEM_LIST
178
debugmem_list_add(p);
179
#endif
180
xmlMutexUnlock(&xmlMemMutex);
181
182
if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint();
183
184
ret = HDR_2_CLIENT(p);
185
186
if (xmlMemTraceBlockAt == ret) {
187
xmlGenericError(xmlGenericErrorContext,
188
"%p : Malloc(%lu) Ok\n", xmlMemTraceBlockAt,
189
(long unsigned)size);
190
xmlMallocBreakpoint();
191
}
192
193
TEST_POINT
194
195
return(ret);
196
}
197
198
/**
199
* xmlMallocAtomicLoc:
200
* @size: an unsigned int specifying the size in byte to allocate.
201
* @file: the file name or NULL
202
* @line: the line number
203
*
204
* a malloc() equivalent, with logging of the allocation info.
205
*
206
* Returns a pointer to the allocated area or NULL in case of lack of memory.
207
*/
208
209
void *
210
xmlMallocAtomicLoc(size_t size, const char * file, int line)
211
{
212
MEMHDR *p;
213
void *ret;
214
215
xmlInitParser();
216
217
TEST_POINT
218
219
if (size > (MAX_SIZE_T - RESERVE_SIZE)) {
220
xmlGenericError(xmlGenericErrorContext,
221
"xmlMallocAtomicLoc : Unsigned overflow\n");
222
return(NULL);
223
}
224
225
p = (MEMHDR *) malloc(RESERVE_SIZE+size);
226
227
if (!p) {
228
xmlGenericError(xmlGenericErrorContext,
229
"xmlMallocAtomicLoc : Out of free space\n");
230
return(NULL);
231
}
232
p->mh_tag = MEMTAG;
233
p->mh_size = size;
234
p->mh_type = MALLOC_ATOMIC_TYPE;
235
p->mh_file = file;
236
p->mh_line = line;
237
xmlMutexLock(&xmlMemMutex);
238
p->mh_number = ++block;
239
debugMemSize += size;
240
debugMemBlocks++;
241
if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
242
#ifdef MEM_LIST
243
debugmem_list_add(p);
244
#endif
245
xmlMutexUnlock(&xmlMemMutex);
246
247
if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint();
248
249
ret = HDR_2_CLIENT(p);
250
251
if (xmlMemTraceBlockAt == ret) {
252
xmlGenericError(xmlGenericErrorContext,
253
"%p : Malloc(%lu) Ok\n", xmlMemTraceBlockAt,
254
(long unsigned)size);
255
xmlMallocBreakpoint();
256
}
257
258
TEST_POINT
259
260
return(ret);
261
}
262
/**
263
* xmlMemMalloc:
264
* @size: an int specifying the size in byte to allocate.
265
*
266
* a malloc() equivalent, with logging of the allocation info.
267
*
268
* Returns a pointer to the allocated area or NULL in case of lack of memory.
269
*/
270
271
void *
272
xmlMemMalloc(size_t size)
273
{
274
return(xmlMallocLoc(size, "none", 0));
275
}
276
277
/**
278
* xmlReallocLoc:
279
* @ptr: the initial memory block pointer
280
* @size: an int specifying the size in byte to allocate.
281
* @file: the file name or NULL
282
* @line: the line number
283
*
284
* a realloc() equivalent, with logging of the allocation info.
285
*
286
* Returns a pointer to the allocated area or NULL in case of lack of memory.
287
*/
288
289
void *
290
xmlReallocLoc(void *ptr,size_t size, const char * file, int line)
291
{
292
MEMHDR *p, *tmp;
293
unsigned long number;
294
295
if (ptr == NULL)
296
return(xmlMallocLoc(size, file, line));
297
298
xmlInitParser();
299
TEST_POINT
300
301
p = CLIENT_2_HDR(ptr);
302
number = p->mh_number;
303
if (xmlMemStopAtBlock == number) xmlMallocBreakpoint();
304
if (p->mh_tag != MEMTAG) {
305
Mem_Tag_Err(p);
306
goto error;
307
}
308
p->mh_tag = ~MEMTAG;
309
xmlMutexLock(&xmlMemMutex);
310
debugMemSize -= p->mh_size;
311
debugMemBlocks--;
312
#ifdef MEM_LIST
313
debugmem_list_delete(p);
314
#endif
315
xmlMutexUnlock(&xmlMemMutex);
316
317
if (size > (MAX_SIZE_T - RESERVE_SIZE)) {
318
xmlGenericError(xmlGenericErrorContext,
319
"xmlReallocLoc : Unsigned overflow\n");
320
return(NULL);
321
}
322
323
tmp = (MEMHDR *) realloc(p,RESERVE_SIZE+size);
324
if (!tmp) {
325
free(p);
326
goto error;
327
}
328
p = tmp;
329
if (xmlMemTraceBlockAt == ptr) {
330
xmlGenericError(xmlGenericErrorContext,
331
"%p : Realloced(%lu -> %lu) Ok\n",
332
xmlMemTraceBlockAt, (long unsigned)p->mh_size,
333
(long unsigned)size);
334
xmlMallocBreakpoint();
335
}
336
p->mh_tag = MEMTAG;
337
p->mh_number = number;
338
p->mh_type = REALLOC_TYPE;
339
p->mh_size = size;
340
p->mh_file = file;
341
p->mh_line = line;
342
xmlMutexLock(&xmlMemMutex);
343
debugMemSize += size;
344
debugMemBlocks++;
345
if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
346
#ifdef MEM_LIST
347
debugmem_list_add(p);
348
#endif
349
xmlMutexUnlock(&xmlMemMutex);
350
351
TEST_POINT
352
353
return(HDR_2_CLIENT(p));
354
355
error:
356
return(NULL);
357
}
358
359
/**
360
* xmlMemRealloc:
361
* @ptr: the initial memory block pointer
362
* @size: an int specifying the size in byte to allocate.
363
*
364
* a realloc() equivalent, with logging of the allocation info.
365
*
366
* Returns a pointer to the allocated area or NULL in case of lack of memory.
367
*/
368
369
void *
370
xmlMemRealloc(void *ptr,size_t size) {
371
return(xmlReallocLoc(ptr, size, "none", 0));
372
}
373
374
/**
375
* xmlMemFree:
376
* @ptr: the memory block pointer
377
*
378
* a free() equivalent, with error checking.
379
*/
380
void
381
xmlMemFree(void *ptr)
382
{
383
MEMHDR *p;
384
char *target;
385
386
if (ptr == NULL)
387
return;
388
389
if (ptr == (void *) -1) {
390
xmlGenericError(xmlGenericErrorContext,
391
"trying to free pointer from freed area\n");
392
goto error;
393
}
394
395
if (xmlMemTraceBlockAt == ptr) {
396
xmlGenericError(xmlGenericErrorContext,
397
"%p : Freed()\n", xmlMemTraceBlockAt);
398
xmlMallocBreakpoint();
399
}
400
401
TEST_POINT
402
403
target = (char *) ptr;
404
405
p = CLIENT_2_HDR(ptr);
406
if (p->mh_tag != MEMTAG) {
407
Mem_Tag_Err(p);
408
goto error;
409
}
410
if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint();
411
p->mh_tag = ~MEMTAG;
412
memset(target, -1, p->mh_size);
413
xmlMutexLock(&xmlMemMutex);
414
debugMemSize -= p->mh_size;
415
debugMemBlocks--;
416
#ifdef MEM_LIST
417
debugmem_list_delete(p);
418
#endif
419
xmlMutexUnlock(&xmlMemMutex);
420
421
free(p);
422
423
TEST_POINT
424
425
return;
426
427
error:
428
xmlGenericError(xmlGenericErrorContext,
429
"xmlMemFree(%p) error\n", ptr);
430
xmlMallocBreakpoint();
431
return;
432
}
433
434
/**
435
* xmlMemStrdupLoc:
436
* @str: the initial string pointer
437
* @file: the file name or NULL
438
* @line: the line number
439
*
440
* a strdup() equivalent, with logging of the allocation info.
441
*
442
* Returns a pointer to the new string or NULL if allocation error occurred.
443
*/
444
445
char *
446
xmlMemStrdupLoc(const char *str, const char *file, int line)
447
{
448
char *s;
449
size_t size = strlen(str) + 1;
450
MEMHDR *p;
451
452
xmlInitParser();
453
TEST_POINT
454
455
if (size > (MAX_SIZE_T - RESERVE_SIZE)) {
456
xmlGenericError(xmlGenericErrorContext,
457
"xmlMemStrdupLoc : Unsigned overflow\n");
458
return(NULL);
459
}
460
461
p = (MEMHDR *) malloc(RESERVE_SIZE+size);
462
if (!p) {
463
goto error;
464
}
465
p->mh_tag = MEMTAG;
466
p->mh_size = size;
467
p->mh_type = STRDUP_TYPE;
468
p->mh_file = file;
469
p->mh_line = line;
470
xmlMutexLock(&xmlMemMutex);
471
p->mh_number = ++block;
472
debugMemSize += size;
473
debugMemBlocks++;
474
if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
475
#ifdef MEM_LIST
476
debugmem_list_add(p);
477
#endif
478
xmlMutexUnlock(&xmlMemMutex);
479
480
s = (char *) HDR_2_CLIENT(p);
481
482
if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint();
483
484
strcpy(s,str);
485
486
TEST_POINT
487
488
if (xmlMemTraceBlockAt == s) {
489
xmlGenericError(xmlGenericErrorContext,
490
"%p : Strdup() Ok\n", xmlMemTraceBlockAt);
491
xmlMallocBreakpoint();
492
}
493
494
return(s);
495
496
error:
497
return(NULL);
498
}
499
500
/**
501
* xmlMemoryStrdup:
502
* @str: the initial string pointer
503
*
504
* a strdup() equivalent, with logging of the allocation info.
505
*
506
* Returns a pointer to the new string or NULL if allocation error occurred.
507
*/
508
509
char *
510
xmlMemoryStrdup(const char *str) {
511
return(xmlMemStrdupLoc(str, "none", 0));
512
}
513
514
/**
515
* xmlMemSize:
516
* @ptr: pointer to the memory allocation
517
*
518
* Returns the size of a memory allocation.
519
*/
520
521
size_t
522
xmlMemSize(void *ptr) {
523
MEMHDR *p;
524
525
if (ptr == NULL)
526
return(0);
527
528
p = CLIENT_2_HDR(ptr);
529
if (p->mh_tag != MEMTAG)
530
return(0);
531
532
return(p->mh_size);
533
}
534
535
/**
536
* xmlMemUsed:
537
*
538
* Provides the amount of memory currently allocated
539
*
540
* Returns an int representing the amount of memory allocated.
541
*/
542
543
int
544
xmlMemUsed(void) {
545
return(debugMemSize);
546
}
547
548
/**
549
* xmlMemBlocks:
550
*
551
* Provides the number of memory areas currently allocated
552
*
553
* Returns an int representing the number of blocks
554
*/
555
556
int
557
xmlMemBlocks(void) {
558
int res;
559
560
xmlMutexLock(&xmlMemMutex);
561
res = debugMemBlocks;
562
xmlMutexUnlock(&xmlMemMutex);
563
return(res);
564
}
565
566
/**
567
* xmlMemDisplayLast:
568
* @fp: a FILE descriptor used as the output file, if NULL, the result is
569
* written to the file .memorylist
570
* @nbBytes: the amount of memory to dump
571
*
572
* the last nbBytes of memory allocated and not freed, useful for dumping
573
* the memory left allocated between two places at runtime.
574
*/
575
576
void
577
xmlMemDisplayLast(FILE *fp, long nbBytes)
578
{
579
#ifdef MEM_LIST
580
MEMHDR *p;
581
unsigned idx;
582
int nb = 0;
583
#endif
584
FILE *old_fp = fp;
585
586
if (nbBytes <= 0)
587
return;
588
589
if (fp == NULL) {
590
fp = fopen(".memorylist", "w");
591
if (fp == NULL)
592
return;
593
}
594
595
#ifdef MEM_LIST
596
fprintf(fp," Last %li MEMORY ALLOCATED : %lu, MAX was %lu\n",
597
nbBytes, debugMemSize, debugMaxMemSize);
598
fprintf(fp,"BLOCK NUMBER SIZE TYPE\n");
599
idx = 0;
600
xmlMutexLock(&xmlMemMutex);
601
p = memlist;
602
while ((p) && (nbBytes > 0)) {
603
fprintf(fp,"%-5u %6lu %6lu ",idx++,p->mh_number,
604
(unsigned long)p->mh_size);
605
switch (p->mh_type) {
606
case STRDUP_TYPE:fprintf(fp,"strdup() in ");break;
607
case MALLOC_TYPE:fprintf(fp,"malloc() in ");break;
608
case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
609
case MALLOC_ATOMIC_TYPE:fprintf(fp,"atomicmalloc() in ");break;
610
case REALLOC_ATOMIC_TYPE:fprintf(fp,"atomicrealloc() in ");break;
611
default:
612
fprintf(fp,"Unknown memory block, may be corrupted");
613
xmlMutexUnlock(&xmlMemMutex);
614
if (old_fp == NULL)
615
fclose(fp);
616
return;
617
}
618
if (p->mh_file != NULL) fprintf(fp,"%s(%u)", p->mh_file, p->mh_line);
619
if (p->mh_tag != MEMTAG)
620
fprintf(fp," INVALID");
621
nb++;
622
623
fprintf(fp,"\n");
624
nbBytes -= (unsigned long)p->mh_size;
625
p = p->mh_next;
626
}
627
xmlMutexUnlock(&xmlMemMutex);
628
#else
629
fprintf(fp,"Memory list not compiled (MEM_LIST not defined !)\n");
630
#endif
631
if (old_fp == NULL)
632
fclose(fp);
633
}
634
635
/**
636
* xmlMemDisplay:
637
* @fp: a FILE descriptor used as the output file, if NULL, the result is
638
* written to the file .memorylist
639
*
640
* show in-extenso the memory blocks allocated
641
*/
642
643
void
644
xmlMemDisplay(FILE *fp)
645
{
646
#ifdef MEM_LIST
647
MEMHDR *p;
648
unsigned idx;
649
int nb = 0;
650
time_t currentTime;
651
char buf[500];
652
struct tm * tstruct;
653
#endif
654
FILE *old_fp = fp;
655
656
if (fp == NULL) {
657
fp = fopen(".memorylist", "w");
658
if (fp == NULL)
659
return;
660
}
661
662
#ifdef MEM_LIST
663
currentTime = time(NULL);
664
tstruct = localtime(&currentTime);
665
strftime(buf, sizeof(buf) - 1, "%I:%M:%S %p", tstruct);
666
fprintf(fp," %s\n\n", buf);
667
668
669
fprintf(fp," MEMORY ALLOCATED : %lu, MAX was %lu\n",
670
debugMemSize, debugMaxMemSize);
671
fprintf(fp,"BLOCK NUMBER SIZE TYPE\n");
672
idx = 0;
673
xmlMutexLock(&xmlMemMutex);
674
p = memlist;
675
while (p) {
676
fprintf(fp,"%-5u %6lu %6lu ",idx++,p->mh_number,
677
(unsigned long)p->mh_size);
678
switch (p->mh_type) {
679
case STRDUP_TYPE:fprintf(fp,"strdup() in ");break;
680
case MALLOC_TYPE:fprintf(fp,"malloc() in ");break;
681
case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
682
case MALLOC_ATOMIC_TYPE:fprintf(fp,"atomicmalloc() in ");break;
683
case REALLOC_ATOMIC_TYPE:fprintf(fp,"atomicrealloc() in ");break;
684
default:
685
fprintf(fp,"Unknown memory block, may be corrupted");
686
xmlMutexUnlock(&xmlMemMutex);
687
if (old_fp == NULL)
688
fclose(fp);
689
return;
690
}
691
if (p->mh_file != NULL) fprintf(fp,"%s(%u)", p->mh_file, p->mh_line);
692
if (p->mh_tag != MEMTAG)
693
fprintf(fp," INVALID");
694
nb++;
695
696
fprintf(fp,"\n");
697
p = p->mh_next;
698
}
699
xmlMutexUnlock(&xmlMemMutex);
700
#else
701
fprintf(fp,"Memory list not compiled (MEM_LIST not defined !)\n");
702
#endif
703
if (old_fp == NULL)
704
fclose(fp);
705
}
706
707
#ifdef MEM_LIST
708
709
static void debugmem_list_add(MEMHDR *p)
710
{
711
p->mh_next = memlist;
712
p->mh_prev = NULL;
713
if (memlist) memlist->mh_prev = p;
714
memlist = p;
715
}
716
717
static void debugmem_list_delete(MEMHDR *p)
718
{
719
if (p->mh_next)
720
p->mh_next->mh_prev = p->mh_prev;
721
if (p->mh_prev)
722
p->mh_prev->mh_next = p->mh_next;
723
else memlist = p->mh_next;
724
}
725
726
#endif
727
728
/*
729
* debugmem_tag_error:
730
*
731
* internal error function.
732
*/
733
734
static void debugmem_tag_error(void *p)
735
{
736
xmlGenericError(xmlGenericErrorContext,
737
"Memory tag error occurs :%p \n\t bye\n", p);
738
#ifdef MEM_LIST
739
if (stderr)
740
xmlMemDisplay(stderr);
741
#endif
742
}
743
744
#ifdef MEM_LIST
745
static FILE *xmlMemoryDumpFile = NULL;
746
#endif
747
748
/**
749
* xmlMemShow:
750
* @fp: a FILE descriptor used as the output file
751
* @nr: number of entries to dump
752
*
753
* show a show display of the memory allocated, and dump
754
* the @nr last allocated areas which were not freed
755
*/
756
757
void
758
xmlMemShow(FILE *fp, int nr ATTRIBUTE_UNUSED)
759
{
760
#ifdef MEM_LIST
761
MEMHDR *p;
762
#endif
763
764
if (fp != NULL)
765
fprintf(fp," MEMORY ALLOCATED : %lu, MAX was %lu\n",
766
debugMemSize, debugMaxMemSize);
767
#ifdef MEM_LIST
768
xmlMutexLock(&xmlMemMutex);
769
if (nr > 0) {
770
fprintf(fp,"NUMBER SIZE TYPE WHERE\n");
771
p = memlist;
772
while ((p) && nr > 0) {
773
fprintf(fp,"%6lu %6lu ",p->mh_number,(unsigned long)p->mh_size);
774
switch (p->mh_type) {
775
case STRDUP_TYPE:fprintf(fp,"strdup() in ");break;
776
case MALLOC_TYPE:fprintf(fp,"malloc() in ");break;
777
case MALLOC_ATOMIC_TYPE:fprintf(fp,"atomicmalloc() in ");break;
778
case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
779
case REALLOC_ATOMIC_TYPE:fprintf(fp,"atomicrealloc() in ");break;
780
default:fprintf(fp," ??? in ");break;
781
}
782
if (p->mh_file != NULL)
783
fprintf(fp,"%s(%u)", p->mh_file, p->mh_line);
784
if (p->mh_tag != MEMTAG)
785
fprintf(fp," INVALID");
786
fprintf(fp,"\n");
787
nr--;
788
p = p->mh_next;
789
}
790
}
791
xmlMutexUnlock(&xmlMemMutex);
792
#endif /* MEM_LIST */
793
}
794
795
/**
796
* xmlMemoryDump:
797
*
798
* Dump in-extenso the memory blocks allocated to the file .memorylist
799
*/
800
801
void
802
xmlMemoryDump(void)
803
{
804
#ifdef MEM_LIST
805
FILE *dump;
806
807
if (debugMaxMemSize == 0)
808
return;
809
dump = fopen(".memdump", "w");
810
if (dump == NULL)
811
xmlMemoryDumpFile = stderr;
812
else xmlMemoryDumpFile = dump;
813
814
xmlMemDisplay(xmlMemoryDumpFile);
815
816
if (dump != NULL) fclose(dump);
817
#endif /* MEM_LIST */
818
}
819
820
821
/****************************************************************
822
* *
823
* Initialization Routines *
824
* *
825
****************************************************************/
826
827
/**
828
* xmlInitMemory:
829
*
830
* DEPRECATED: Alias for xmlInitParser.
831
*/
832
int
833
xmlInitMemory(void) {
834
xmlInitParser();
835
return(0);
836
}
837
838
/**
839
* xmlInitMemoryInternal:
840
*
841
* Initialize the memory layer.
842
*
843
* Returns 0 on success
844
*/
845
void
846
xmlInitMemoryInternal(void) {
847
char *breakpoint;
848
xmlInitMutex(&xmlMemMutex);
849
850
breakpoint = getenv("XML_MEM_BREAKPOINT");
851
if (breakpoint != NULL) {
852
sscanf(breakpoint, "%ud", &xmlMemStopAtBlock);
853
}
854
breakpoint = getenv("XML_MEM_TRACE");
855
if (breakpoint != NULL) {
856
sscanf(breakpoint, "%p", &xmlMemTraceBlockAt);
857
}
858
859
}
860
861
/**
862
* xmlCleanupMemory:
863
*
864
* DEPRECATED: This function is a no-op. Call xmlCleanupParser
865
* to free global state but see the warnings there. xmlCleanupParser
866
* should be only called once at program exit. In most cases, you don't
867
* have call cleanup functions at all.
868
*/
869
void
870
xmlCleanupMemory(void) {
871
}
872
873
/**
874
* xmlCleanupMemoryInternal:
875
*
876
* Free up all the memory allocated by the library for its own
877
* use. This should not be called by user level code.
878
*/
879
void
880
xmlCleanupMemoryInternal(void) {
881
/*
882
* Don't clean up mutex on Windows. Global state destructors can call
883
* malloc functions after xmlCleanupParser was called. If memory
884
* debugging is enabled, xmlMemMutex can be used after cleanup.
885
*
886
* See python/tests/thread2.py
887
*/
888
#if !defined(LIBXML_THREAD_ENABLED) || !defined(_WIN32)
889
xmlCleanupMutex(&xmlMemMutex);
890
#endif
891
}
892
893
/**
894
* xmlMemSetup:
895
* @freeFunc: the free() function to use
896
* @mallocFunc: the malloc() function to use
897
* @reallocFunc: the realloc() function to use
898
* @strdupFunc: the strdup() function to use
899
*
900
* Override the default memory access functions with a new set
901
* This has to be called before any other libxml routines !
902
*
903
* Should this be blocked if there was already some allocations
904
* done ?
905
*
906
* Returns 0 on success
907
*/
908
int
909
xmlMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc,
910
xmlReallocFunc reallocFunc, xmlStrdupFunc strdupFunc) {
911
if (freeFunc == NULL)
912
return(-1);
913
if (mallocFunc == NULL)
914
return(-1);
915
if (reallocFunc == NULL)
916
return(-1);
917
if (strdupFunc == NULL)
918
return(-1);
919
xmlFree = freeFunc;
920
xmlMalloc = mallocFunc;
921
xmlMallocAtomic = mallocFunc;
922
xmlRealloc = reallocFunc;
923
xmlMemStrdup = strdupFunc;
924
return(0);
925
}
926
927
/**
928
* xmlMemGet:
929
* @freeFunc: place to save the free() function in use
930
* @mallocFunc: place to save the malloc() function in use
931
* @reallocFunc: place to save the realloc() function in use
932
* @strdupFunc: place to save the strdup() function in use
933
*
934
* Provides the memory access functions set currently in use
935
*
936
* Returns 0 on success
937
*/
938
int
939
xmlMemGet(xmlFreeFunc *freeFunc, xmlMallocFunc *mallocFunc,
940
xmlReallocFunc *reallocFunc, xmlStrdupFunc *strdupFunc) {
941
if (freeFunc != NULL) *freeFunc = xmlFree;
942
if (mallocFunc != NULL) *mallocFunc = xmlMalloc;
943
if (reallocFunc != NULL) *reallocFunc = xmlRealloc;
944
if (strdupFunc != NULL) *strdupFunc = xmlMemStrdup;
945
return(0);
946
}
947
948
/**
949
* xmlGcMemSetup:
950
* @freeFunc: the free() function to use
951
* @mallocFunc: the malloc() function to use
952
* @mallocAtomicFunc: the malloc() function to use for atomic allocations
953
* @reallocFunc: the realloc() function to use
954
* @strdupFunc: the strdup() function to use
955
*
956
* Override the default memory access functions with a new set
957
* This has to be called before any other libxml routines !
958
* The mallocAtomicFunc is specialized for atomic block
959
* allocations (i.e. of areas useful for garbage collected memory allocators
960
*
961
* Should this be blocked if there was already some allocations
962
* done ?
963
*
964
* Returns 0 on success
965
*/
966
int
967
xmlGcMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc,
968
xmlMallocFunc mallocAtomicFunc, xmlReallocFunc reallocFunc,
969
xmlStrdupFunc strdupFunc) {
970
if (freeFunc == NULL)
971
return(-1);
972
if (mallocFunc == NULL)
973
return(-1);
974
if (mallocAtomicFunc == NULL)
975
return(-1);
976
if (reallocFunc == NULL)
977
return(-1);
978
if (strdupFunc == NULL)
979
return(-1);
980
xmlFree = freeFunc;
981
xmlMalloc = mallocFunc;
982
xmlMallocAtomic = mallocAtomicFunc;
983
xmlRealloc = reallocFunc;
984
xmlMemStrdup = strdupFunc;
985
return(0);
986
}
987
988
/**
989
* xmlGcMemGet:
990
* @freeFunc: place to save the free() function in use
991
* @mallocFunc: place to save the malloc() function in use
992
* @mallocAtomicFunc: place to save the atomic malloc() function in use
993
* @reallocFunc: place to save the realloc() function in use
994
* @strdupFunc: place to save the strdup() function in use
995
*
996
* Provides the memory access functions set currently in use
997
* The mallocAtomicFunc is specialized for atomic block
998
* allocations (i.e. of areas useful for garbage collected memory allocators
999
*
1000
* Returns 0 on success
1001
*/
1002
int
1003
xmlGcMemGet(xmlFreeFunc *freeFunc, xmlMallocFunc *mallocFunc,
1004
xmlMallocFunc *mallocAtomicFunc, xmlReallocFunc *reallocFunc,
1005
xmlStrdupFunc *strdupFunc) {
1006
if (freeFunc != NULL) *freeFunc = xmlFree;
1007
if (mallocFunc != NULL) *mallocFunc = xmlMalloc;
1008
if (mallocAtomicFunc != NULL) *mallocAtomicFunc = xmlMallocAtomic;
1009
if (reallocFunc != NULL) *reallocFunc = xmlRealloc;
1010
if (strdupFunc != NULL) *strdupFunc = xmlMemStrdup;
1011
return(0);
1012
}
1013
1014