VirtualBox

source: vbox/trunk/src/libs/libxml2-2.13.2/xmlmemory.c@ 105420

最後變更 在這個檔案從105420是 105420,由 vboxsync 提交於 4 月 前

libxml2-2.12.6: Applied and adjusted our libxml2 changes to 2.12.6. bugref:10730

  • 屬性 svn:eol-style 設為 native
檔案大小: 13.7 KB
 
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
35static int xmlMemInitialized = 0;
36static unsigned long debugMemSize = 0;
37static unsigned long debugMemBlocks = 0;
38static xmlMutex xmlMemMutex;
39
40/************************************************************************
41 * *
42 * Macros, variables and associated types *
43 * *
44 ************************************************************************/
45
46#if !defined(LIBXML_THREAD_ENABLED) && !defined(LIBXML_THREAD_ALLOC_ENABLED)
47 #ifdef xmlMalloc
48 #undef xmlMalloc
49 #endif
50
51 #ifdef xmlRealloc
52 #undef xmlRealloc
53 #endif
54
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
66typedef struct memnod {
67 unsigned int mh_tag;
68 size_t mh_size;
69} MEMHDR;
70
71#ifdef SUN4
72#define ALIGN_SIZE 16
73#else
74#define ALIGN_SIZE sizeof(double)
75#endif
76
77#define HDR_SIZE sizeof(MEMHDR)
78#define RESERVE_SIZE (((HDR_SIZE + (ALIGN_SIZE-1)) \
79 / ALIGN_SIZE ) * ALIGN_SIZE)
80
81#define MAX_SIZE_T ((size_t)-1)
82
83#define CLIENT_2_HDR(a) ((void *) (((char *) (a)) - RESERVE_SIZE))
84#define HDR_2_CLIENT(a) ((void *) (((char *) (a)) + RESERVE_SIZE))
85
86/**
87 * xmlMallocLoc:
88 * @size: an int specifying the size in byte to allocate.
89 * @file: the file name or NULL
90 * @line: the line number
91 *
92 * DEPRECATED: don't use
93 *
94 * Returns a pointer to the allocated area or NULL in case of lack of memory.
95 */
96void *
97xmlMallocLoc(size_t size, const char *file ATTRIBUTE_UNUSED,
98 int line ATTRIBUTE_UNUSED)
99{
100 return(xmlMemMalloc(size));
101}
102
103/**
104 * xmlMallocAtomicLoc:
105 * @size: an unsigned int specifying the size in byte to allocate.
106 * @file: the file name or NULL
107 * @line: the line number
108 *
109 * DEPRECATED: don't use
110 *
111 * Returns a pointer to the allocated area or NULL in case of lack of memory.
112 */
113void *
114xmlMallocAtomicLoc(size_t size, const char *file ATTRIBUTE_UNUSED,
115 int line ATTRIBUTE_UNUSED)
116{
117 return(xmlMemMalloc(size));
118}
119
120/**
121 * xmlMemMalloc:
122 * @size: an int specifying the size in byte to allocate.
123 *
124 * a malloc() equivalent, with logging of the allocation info.
125 *
126 * Returns a pointer to the allocated area or NULL in case of lack of memory.
127 */
128void *
129xmlMemMalloc(size_t size)
130{
131 MEMHDR *p;
132
133 xmlInitParser();
134
135 if (size > (MAX_SIZE_T - RESERVE_SIZE)) {
136 fprintf(stderr, "xmlMemMalloc: Unsigned overflow\n");
137 return(NULL);
138 }
139
140 p = (MEMHDR *) malloc(RESERVE_SIZE + size);
141 if (!p) {
142 fprintf(stderr, "xmlMemMalloc: Out of memory\n");
143 return(NULL);
144 }
145 p->mh_tag = MEMTAG;
146 p->mh_size = size;
147
148 xmlMutexLock(&xmlMemMutex);
149 debugMemSize += size;
150 debugMemBlocks++;
151 xmlMutexUnlock(&xmlMemMutex);
152
153 return(HDR_2_CLIENT(p));
154}
155
156/**
157 * xmlReallocLoc:
158 * @ptr: the initial memory block pointer
159 * @size: an int specifying the size in byte to allocate.
160 * @file: the file name or NULL
161 * @line: the line number
162 *
163 * DEPRECATED: don't use
164 *
165 * Returns a pointer to the allocated area or NULL in case of lack of memory.
166 */
167void *
168xmlReallocLoc(void *ptr, size_t size, const char *file ATTRIBUTE_UNUSED,
169 int line ATTRIBUTE_UNUSED)
170{
171 return(xmlMemRealloc(ptr, size));
172}
173
174/**
175 * xmlMemRealloc:
176 * @ptr: the initial memory block pointer
177 * @size: an int specifying the size in byte to allocate.
178 *
179 * a realloc() equivalent, with logging of the allocation info.
180 *
181 * Returns a pointer to the allocated area or NULL in case of lack of memory.
182 */
183void *
184xmlMemRealloc(void *ptr, size_t size) {
185 MEMHDR *p, *tmp;
186 size_t oldSize;
187
188 if (ptr == NULL)
189 return(xmlMemMalloc(size));
190
191 xmlInitParser();
192
193 if (size > (MAX_SIZE_T - RESERVE_SIZE)) {
194 fprintf(stderr, "xmlMemRealloc: Unsigned overflow\n");
195 return(NULL);
196 }
197
198 p = CLIENT_2_HDR(ptr);
199 if (p->mh_tag != MEMTAG) {
200 fprintf(stderr, "xmlMemRealloc: Tag error\n");
201 return(NULL);
202 }
203 oldSize = p->mh_size;
204 p->mh_tag = ~MEMTAG;
205
206 tmp = (MEMHDR *) realloc(p, RESERVE_SIZE + size);
207 if (!tmp) {
208 p->mh_tag = MEMTAG;
209 fprintf(stderr, "xmlMemRealloc: Out of memory\n");
210 return(NULL);
211 }
212 p = tmp;
213 p->mh_tag = MEMTAG;
214 p->mh_size = size;
215
216 xmlMutexLock(&xmlMemMutex);
217 debugMemSize -= oldSize;
218 debugMemSize += size;
219 xmlMutexUnlock(&xmlMemMutex);
220
221 return(HDR_2_CLIENT(p));
222}
223
224/**
225 * xmlMemFree:
226 * @ptr: the memory block pointer
227 *
228 * a free() equivalent, with error checking.
229 */
230void
231xmlMemFree(void *ptr)
232{
233 MEMHDR *p;
234
235 if (ptr == NULL)
236 return;
237
238 if (ptr == (void *) -1) {
239 fprintf(stderr, "xmlMemFree: Pointer from freed area\n");
240 return;
241 }
242
243 p = CLIENT_2_HDR(ptr);
244 if (p->mh_tag != MEMTAG) {
245 fprintf(stderr, "xmlMemFree: Tag error\n");
246 return;
247 }
248 p->mh_tag = ~MEMTAG;
249 memset(ptr, -1, p->mh_size);
250
251 xmlMutexLock(&xmlMemMutex);
252 debugMemSize -= p->mh_size;
253 debugMemBlocks--;
254 xmlMutexUnlock(&xmlMemMutex);
255
256 free(p);
257
258 return;
259}
260
261/**
262 * xmlMemStrdupLoc:
263 * @str: the initial string pointer
264 * @file: the file name or NULL
265 * @line: the line number
266 *
267 * DEPRECATED: don't use
268 *
269 * Returns a pointer to the new string or NULL if allocation error occurred.
270 */
271char *
272xmlMemStrdupLoc(const char *str, const char *file ATTRIBUTE_UNUSED,
273 int line ATTRIBUTE_UNUSED)
274{
275 return(xmlMemoryStrdup(str));
276}
277
278/**
279 * xmlMemoryStrdup:
280 * @str: the initial string pointer
281 *
282 * a strdup() equivalent, with logging of the allocation info.
283 *
284 * Returns a pointer to the new string or NULL if allocation error occurred.
285 */
286char *
287xmlMemoryStrdup(const char *str) {
288 char *s;
289 size_t size = strlen(str) + 1;
290 MEMHDR *p;
291
292 xmlInitParser();
293
294 if (size > (MAX_SIZE_T - RESERVE_SIZE)) {
295 fprintf(stderr, "xmlMemoryStrdup: Unsigned overflow\n");
296 return(NULL);
297 }
298
299 p = (MEMHDR *) malloc(RESERVE_SIZE + size);
300 if (!p) {
301 fprintf(stderr, "xmlMemoryStrdup: Out of memory\n");
302 return(NULL);
303 }
304 p->mh_tag = MEMTAG;
305 p->mh_size = size;
306
307 xmlMutexLock(&xmlMemMutex);
308 debugMemSize += size;
309 debugMemBlocks++;
310 xmlMutexUnlock(&xmlMemMutex);
311
312 s = (char *) HDR_2_CLIENT(p);
313
314 memcpy(s, str, size);
315
316 return(s);
317}
318
319/**
320 * xmlMemSize:
321 * @ptr: pointer to the memory allocation
322 *
323 * Returns the size of a memory allocation.
324 */
325
326size_t
327xmlMemSize(void *ptr) {
328 MEMHDR *p;
329
330 if (ptr == NULL)
331 return(0);
332
333 p = CLIENT_2_HDR(ptr);
334 if (p->mh_tag != MEMTAG)
335 return(0);
336
337 return(p->mh_size);
338}
339
340/**
341 * xmlMemUsed:
342 *
343 * Provides the amount of memory currently allocated
344 *
345 * Returns an int representing the amount of memory allocated.
346 */
347
348int
349xmlMemUsed(void) {
350 return(debugMemSize);
351}
352
353/**
354 * xmlMemBlocks:
355 *
356 * Provides the number of memory areas currently allocated
357 *
358 * Returns an int representing the number of blocks
359 */
360
361int
362xmlMemBlocks(void) {
363 int res;
364
365 xmlMutexLock(&xmlMemMutex);
366 res = debugMemBlocks;
367 xmlMutexUnlock(&xmlMemMutex);
368 return(res);
369}
370
371/**
372 * xmlMemDisplayLast:
373 * @fp: a FILE descriptor
374 * @nbBytes: the amount of memory to dump
375 *
376 * DEPRECATED: This feature was removed.
377 */
378void
379xmlMemDisplayLast(FILE *fp ATTRIBUTE_UNUSED, long nbBytes ATTRIBUTE_UNUSED)
380{
381}
382
383/**
384 * xmlMemDisplay:
385 * @fp: a FILE descriptor
386 *
387 * DEPRECATED: This feature was removed.
388 */
389void
390xmlMemDisplay(FILE *fp ATTRIBUTE_UNUSED)
391{
392}
393
394/**
395 * xmlMemShow:
396 * @fp: a FILE descriptor
397 * @nr: number of entries to dump
398 *
399 * DEPRECATED: This feature was removed.
400 */
401void
402xmlMemShow(FILE *fp ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED)
403{
404}
405
406/**
407 * xmlMemoryDump:
408 *
409 * DEPRECATED: This feature was removed.
410 */
411void
412xmlMemoryDump(void)
413{
414}
415
416
417/****************************************************************
418 * *
419 * Initialization Routines *
420 * *
421 ****************************************************************/
422
423/**
424 * xmlInitMemory:
425 *
426 * DEPRECATED: Alias for xmlInitParser.
427 *
428 * Returns 0.
429 */
430int
431xmlInitMemory(void) {
432 xmlInitParser();
433 return(0);
434}
435
436/**
437 * xmlInitMemoryInternal:
438 *
439 * Initialize the memory layer.
440 */
441void
442xmlInitMemoryInternal(void) {
443
444#ifdef VBOX
445 const char *breakpoint;
446#else
447 char *breakpoint;
448#endif
449
450#ifdef DEBUG_MEMORY
451 xmlGenericError(xmlGenericErrorContext,
452 "xmlInitMemory()\n");
453#endif
454
455 xmlInitMutex(&xmlMemMutex);
456
457 breakpoint = getenv("XML_MEM_BREAKPOINT");
458 if (breakpoint != NULL) {
459 sscanf(breakpoint, "%ud", &xmlMemStopAtBlock);
460 }
461 breakpoint = getenv("XML_MEM_TRACE");
462 if (breakpoint != NULL) {
463 sscanf(breakpoint, "%p", &xmlMemTraceBlockAt);
464 }
465}
466
467/**
468 * xmlCleanupMemory:
469 *
470 * DEPRECATED: This function is a no-op. Call xmlCleanupParser
471 * to free global state but see the warnings there. xmlCleanupParser
472 * should be only called once at program exit. In most cases, you don't
473 * have call cleanup functions at all.
474 */
475void
476xmlCleanupMemory(void) {
477}
478
479/**
480 * xmlCleanupMemoryInternal:
481 *
482 * Free up all the memory allocated by the library for its own
483 * use. This should not be called by user level code.
484 */
485void
486xmlCleanupMemoryInternal(void) {
487 /*
488 * Don't clean up mutex on Windows. Global state destructors can call
489 * malloc functions after xmlCleanupParser was called. If memory
490 * debugging is enabled, xmlMemMutex can be used after cleanup.
491 *
492 * See python/tests/thread2.py
493 */
494#if !defined(LIBXML_THREAD_ENABLED) || !defined(_WIN32)
495 xmlCleanupMutex(&xmlMemMutex);
496#endif
497}
498
499/**
500 * xmlMemSetup:
501 * @freeFunc: the free() function to use
502 * @mallocFunc: the malloc() function to use
503 * @reallocFunc: the realloc() function to use
504 * @strdupFunc: the strdup() function to use
505 *
506 * Override the default memory access functions with a new set
507 * This has to be called before any other libxml routines !
508 *
509 * Should this be blocked if there was already some allocations
510 * done ?
511 *
512 * Returns 0 on success
513 */
514int
515xmlMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc,
516 xmlReallocFunc reallocFunc, xmlStrdupFunc strdupFunc) {
517 if (freeFunc == NULL)
518 return(-1);
519 if (mallocFunc == NULL)
520 return(-1);
521 if (reallocFunc == NULL)
522 return(-1);
523 if (strdupFunc == NULL)
524 return(-1);
525 xmlFree = freeFunc;
526 xmlMalloc = mallocFunc;
527 xmlMallocAtomic = mallocFunc;
528 xmlRealloc = reallocFunc;
529 xmlMemStrdup = strdupFunc;
530 return(0);
531}
532
533/**
534 * xmlMemGet:
535 * @freeFunc: place to save the free() function in use
536 * @mallocFunc: place to save the malloc() function in use
537 * @reallocFunc: place to save the realloc() function in use
538 * @strdupFunc: place to save the strdup() function in use
539 *
540 * Provides the memory access functions set currently in use
541 *
542 * Returns 0 on success
543 */
544int
545xmlMemGet(xmlFreeFunc *freeFunc, xmlMallocFunc *mallocFunc,
546 xmlReallocFunc *reallocFunc, xmlStrdupFunc *strdupFunc) {
547 if (freeFunc != NULL) *freeFunc = xmlFree;
548 if (mallocFunc != NULL) *mallocFunc = xmlMalloc;
549 if (reallocFunc != NULL) *reallocFunc = xmlRealloc;
550 if (strdupFunc != NULL) *strdupFunc = xmlMemStrdup;
551 return(0);
552}
553
554/**
555 * xmlGcMemSetup:
556 * @freeFunc: the free() function to use
557 * @mallocFunc: the malloc() function to use
558 * @mallocAtomicFunc: the malloc() function to use for atomic allocations
559 * @reallocFunc: the realloc() function to use
560 * @strdupFunc: the strdup() function to use
561 *
562 * Override the default memory access functions with a new set
563 * This has to be called before any other libxml routines !
564 * The mallocAtomicFunc is specialized for atomic block
565 * allocations (i.e. of areas useful for garbage collected memory allocators
566 *
567 * Should this be blocked if there was already some allocations
568 * done ?
569 *
570 * Returns 0 on success
571 */
572int
573xmlGcMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc,
574 xmlMallocFunc mallocAtomicFunc, xmlReallocFunc reallocFunc,
575 xmlStrdupFunc strdupFunc) {
576 if (freeFunc == NULL)
577 return(-1);
578 if (mallocFunc == NULL)
579 return(-1);
580 if (mallocAtomicFunc == NULL)
581 return(-1);
582 if (reallocFunc == NULL)
583 return(-1);
584 if (strdupFunc == NULL)
585 return(-1);
586 xmlFree = freeFunc;
587 xmlMalloc = mallocFunc;
588 xmlMallocAtomic = mallocAtomicFunc;
589 xmlRealloc = reallocFunc;
590 xmlMemStrdup = strdupFunc;
591 return(0);
592}
593
594/**
595 * xmlGcMemGet:
596 * @freeFunc: place to save the free() function in use
597 * @mallocFunc: place to save the malloc() function in use
598 * @mallocAtomicFunc: place to save the atomic malloc() function in use
599 * @reallocFunc: place to save the realloc() function in use
600 * @strdupFunc: place to save the strdup() function in use
601 *
602 * Provides the memory access functions set currently in use
603 * The mallocAtomicFunc is specialized for atomic block
604 * allocations (i.e. of areas useful for garbage collected memory allocators
605 *
606 * Returns 0 on success
607 */
608int
609xmlGcMemGet(xmlFreeFunc *freeFunc, xmlMallocFunc *mallocFunc,
610 xmlMallocFunc *mallocAtomicFunc, xmlReallocFunc *reallocFunc,
611 xmlStrdupFunc *strdupFunc) {
612 if (freeFunc != NULL) *freeFunc = xmlFree;
613 if (mallocFunc != NULL) *mallocFunc = xmlMalloc;
614 if (mallocAtomicFunc != NULL) *mallocAtomicFunc = xmlMallocAtomic;
615 if (reallocFunc != NULL) *reallocFunc = xmlRealloc;
616 if (strdupFunc != NULL) *strdupFunc = xmlMemStrdup;
617 return(0);
618}
619
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette