ReactOS 0.4.16-dev-2354-g16de117
ftdbgmem.c
Go to the documentation of this file.
1/****************************************************************************
2 *
3 * ftdbgmem.c
4 *
5 * Memory debugger (body).
6 *
7 * Copyright (C) 2001-2020 by
8 * David Turner, Robert Wilhelm, and Werner Lemberg.
9 *
10 * This file is part of the FreeType project, and may only be used,
11 * modified, and distributed under the terms of the FreeType project
12 * license, LICENSE.TXT. By continuing to use, modify, or distribute
13 * this file you indicate that you have read the license and
14 * understand and accept it fully.
15 *
16 */
17
18
19#include <ft2build.h>
20#include FT_CONFIG_CONFIG_H
23#include <freetype/ftsystem.h>
24#include <freetype/fterrors.h>
25#include <freetype/fttypes.h>
26
27
28#ifdef FT_DEBUG_MEMORY
29
30#define KEEPALIVE /* `Keep alive' means that freed blocks aren't released
31 * to the heap. This is useful to detect double-frees
32 * or weird heap corruption, but it uses large amounts of
33 * memory, however.
34 */
35
36#include FT_CONFIG_STANDARD_LIBRARY_H
37
38 FT_BASE_DEF( const char* ) _ft_debug_file = NULL;
39 FT_BASE_DEF( long ) _ft_debug_lineno = 0;
40
41 extern void
42 FT_DumpMemory( FT_Memory memory );
43
44
45 typedef struct FT_MemSourceRec_* FT_MemSource;
46 typedef struct FT_MemNodeRec_* FT_MemNode;
47 typedef struct FT_MemTableRec_* FT_MemTable;
48
49
50#define FT_MEM_VAL( addr ) ( (FT_PtrDist)(FT_Pointer)( addr ) )
51
52 /*
53 * This structure holds statistics for a single allocation/release
54 * site. This is useful to know where memory operations happen the
55 * most.
56 */
57 typedef struct FT_MemSourceRec_
58 {
59 const char* file_name;
60 long line_no;
61
62 FT_Long cur_blocks; /* current number of allocated blocks */
63 FT_Long max_blocks; /* max. number of allocated blocks */
64 FT_Long all_blocks; /* total number of blocks allocated */
65
66 FT_Long cur_size; /* current cumulative allocated size */
67 FT_Long max_size; /* maximum cumulative allocated size */
68 FT_Long all_size; /* total cumulative allocated size */
69
70 FT_Long cur_max; /* current maximum allocated size */
71
72 FT_UInt32 hash;
73 FT_MemSource link;
74
75 } FT_MemSourceRec;
76
77
78 /*
79 * We don't need a resizable array for the memory sources because
80 * their number is pretty limited within FreeType.
81 */
82#define FT_MEM_SOURCE_BUCKETS 128
83
84 /*
85 * This structure holds information related to a single allocated
86 * memory block. If KEEPALIVE is defined, blocks that are freed by
87 * FreeType are never released to the system. Instead, their `size'
88 * field is set to `-size'. This is mainly useful to detect double
89 * frees, at the price of a large memory footprint during execution.
90 */
91 typedef struct FT_MemNodeRec_
92 {
94 FT_Long size; /* < 0 if the block was freed */
95
96 FT_MemSource source;
97
98#ifdef KEEPALIVE
99 const char* free_file_name;
100 FT_Long free_line_no;
101#endif
102
103 FT_MemNode link;
104
105 } FT_MemNodeRec;
106
107
108 /*
109 * The global structure, containing compound statistics and all hash
110 * tables.
111 */
112 typedef struct FT_MemTableRec_
113 {
115 FT_Long nodes;
116 FT_MemNode* buckets;
117
118 FT_Long alloc_total;
119 FT_Long alloc_current;
120 FT_Long alloc_max;
122
123 FT_Bool bound_total;
124 FT_Long alloc_total_max;
125
126 FT_Bool bound_count;
127 FT_Long alloc_count_max;
128
129 FT_MemSource sources[FT_MEM_SOURCE_BUCKETS];
130
131 FT_Bool keep_alive;
132
134 FT_Pointer memory_user;
138
139 } FT_MemTableRec;
140
141
142#define FT_MEM_SIZE_MIN 7
143#define FT_MEM_SIZE_MAX 13845163
144
145#define FT_FILENAME( x ) ( (x) ? (x) : "unknown file" )
146
147
148 /*
149 * Prime numbers are ugly to handle. It would be better to implement
150 * L-Hashing, which is 10% faster and doesn't require divisions.
151 */
152 static const FT_Int ft_mem_primes[] =
153 {
154 7,
155 11,
156 19,
157 37,
158 73,
159 109,
160 163,
161 251,
162 367,
163 557,
164 823,
165 1237,
166 1861,
167 2777,
168 4177,
169 6247,
170 9371,
171 14057,
172 21089,
173 31627,
174 47431,
175 71143,
176 106721,
177 160073,
178 240101,
179 360163,
180 540217,
181 810343,
182 1215497,
183 1823231,
184 2734867,
185 4102283,
186 6153409,
187 9230113,
188 13845163,
189 };
190
191
192 static FT_Long
193 ft_mem_closest_prime( FT_Long num )
194 {
195 size_t i;
196
197
198 for ( i = 0;
199 i < sizeof ( ft_mem_primes ) / sizeof ( ft_mem_primes[0] ); i++ )
200 if ( ft_mem_primes[i] > num )
201 return ft_mem_primes[i];
202
203 return FT_MEM_SIZE_MAX;
204 }
205
206
207 static void
208 ft_mem_debug_panic( const char* fmt,
209 ... )
210 {
211 va_list ap;
212
213
214 printf( "FreeType.Debug: " );
215
216 va_start( ap, fmt );
217 vprintf( fmt, ap );
218 va_end( ap );
219
220 printf( "\n" );
222 }
223
224
225 static FT_Pointer
226 ft_mem_table_alloc( FT_MemTable table,
227 FT_Long size )
228 {
229 FT_Memory memory = table->memory;
231
232
233 memory->user = table->memory_user;
234 block = table->alloc( memory, size );
235 memory->user = table;
236
237 return block;
238 }
239
240
241 static void
242 ft_mem_table_free( FT_MemTable table,
244 {
245 FT_Memory memory = table->memory;
246
247
248 memory->user = table->memory_user;
249 table->free( memory, block );
250 memory->user = table;
251 }
252
253
254 static void
255 ft_mem_table_resize( FT_MemTable table )
256 {
258
259
260 new_size = ft_mem_closest_prime( table->nodes );
261 if ( new_size != table->size )
262 {
263 FT_MemNode* new_buckets;
264 FT_Long i;
265
266
267 new_buckets = (FT_MemNode *)
268 ft_mem_table_alloc(
269 table,
270 new_size * (FT_Long)sizeof ( FT_MemNode ) );
271 if ( !new_buckets )
272 return;
273
274 FT_ARRAY_ZERO( new_buckets, new_size );
275
276 for ( i = 0; i < table->size; i++ )
277 {
278 FT_MemNode node, next, *pnode;
280
281
282 node = table->buckets[i];
283 while ( node )
284 {
285 next = node->link;
286 hash = FT_MEM_VAL( node->address ) % (FT_PtrDist)new_size;
287 pnode = new_buckets + hash;
288
289 node->link = pnode[0];
290 pnode[0] = node;
291
292 node = next;
293 }
294 }
295
296 if ( table->buckets )
297 ft_mem_table_free( table, table->buckets );
298
299 table->buckets = new_buckets;
300 table->size = new_size;
301 }
302 }
303
304
305 static FT_MemTable
306 ft_mem_table_new( FT_Memory memory )
307 {
308 FT_MemTable table;
309
310
311 table = (FT_MemTable)memory->alloc( memory, sizeof ( *table ) );
312 if ( !table )
313 goto Exit;
314
315 FT_ZERO( table );
316
317 table->size = FT_MEM_SIZE_MIN;
318 table->nodes = 0;
319
320 table->memory = memory;
321
322 table->memory_user = memory->user;
323
324 table->alloc = memory->alloc;
325 table->realloc = memory->realloc;
326 table->free = memory->free;
327
328 table->buckets = (FT_MemNode *)
329 memory->alloc(
330 memory,
331 table->size * (FT_Long)sizeof ( FT_MemNode ) );
332 if ( table->buckets )
333 FT_ARRAY_ZERO( table->buckets, table->size );
334 else
335 {
336 memory->free( memory, table );
337 table = NULL;
338 }
339
340 Exit:
341 return table;
342 }
343
344
345 static void
346 ft_mem_table_destroy( FT_MemTable table )
347 {
348 FT_Long i;
349 FT_Long leak_count = 0;
350 FT_Long leaks = 0;
351
352
353 FT_DumpMemory( table->memory );
354
355 /* remove all blocks from the table, revealing leaked ones */
356 for ( i = 0; i < table->size; i++ )
357 {
358 FT_MemNode *pnode = table->buckets + i, next, node = *pnode;
359
360
361 while ( node )
362 {
363 next = node->link;
364 node->link = NULL;
365
366 if ( node->size > 0 )
367 {
368 printf(
369 "leaked memory block at address %p, size %8ld in (%s:%ld)\n",
370 (void*)node->address,
371 node->size,
372 FT_FILENAME( node->source->file_name ),
373 node->source->line_no );
374
375 leak_count++;
376 leaks += node->size;
377
378 ft_mem_table_free( table, node->address );
379 }
380
381 node->address = NULL;
382 node->size = 0;
383
384 ft_mem_table_free( table, node );
385 node = next;
386 }
387 table->buckets[i] = NULL;
388 }
389
390 ft_mem_table_free( table, table->buckets );
391 table->buckets = NULL;
392
393 table->size = 0;
394 table->nodes = 0;
395
396 /* remove all sources */
397 for ( i = 0; i < FT_MEM_SOURCE_BUCKETS; i++ )
398 {
399 FT_MemSource source, next;
400
401
402 for ( source = table->sources[i]; source != NULL; source = next )
403 {
404 next = source->link;
405 ft_mem_table_free( table, source );
406 }
407
408 table->sources[i] = NULL;
409 }
410
411 printf( "FreeType: total memory allocations = %ld\n",
412 table->alloc_total );
413 printf( "FreeType: maximum memory footprint = %ld\n",
414 table->alloc_max );
415
416 ft_mem_table_free( table, table );
417
418 if ( leak_count > 0 )
419 ft_mem_debug_panic(
420 "FreeType: %ld bytes of memory leaked in %ld blocks\n",
421 leaks, leak_count );
422
423 printf( "FreeType: no memory leaks detected\n" );
424 }
425
426
427 static FT_MemNode*
428 ft_mem_table_get_nodep( FT_MemTable table,
430 {
432 FT_MemNode *pnode, node;
433
434
435 hash = FT_MEM_VAL( address );
436 pnode = table->buckets + ( hash % (FT_PtrDist)table->size );
437
438 for (;;)
439 {
440 node = pnode[0];
441 if ( !node )
442 break;
443
444 if ( node->address == address )
445 break;
446
447 pnode = &node->link;
448 }
449 return pnode;
450 }
451
452
453 static FT_MemSource
454 ft_mem_table_get_source( FT_MemTable table )
455 {
456 FT_UInt32 hash;
457 FT_MemSource node, *pnode;
458
459
460 /* cast to FT_PtrDist first since void* can be larger */
461 /* than FT_UInt32 and GCC 4.1.1 emits a warning */
462 hash = (FT_UInt32)(FT_PtrDist)(void*)_ft_debug_file +
463 (FT_UInt32)( 5 * _ft_debug_lineno );
464 pnode = &table->sources[hash % FT_MEM_SOURCE_BUCKETS];
465
466 for (;;)
467 {
468 node = *pnode;
469 if ( !node )
470 break;
471
472 if ( node->file_name == _ft_debug_file &&
473 node->line_no == _ft_debug_lineno )
474 goto Exit;
475
476 pnode = &node->link;
477 }
478
479 node = (FT_MemSource)ft_mem_table_alloc( table, sizeof ( *node ) );
480 if ( !node )
481 ft_mem_debug_panic(
482 "not enough memory to perform memory debugging\n" );
483
484 node->file_name = _ft_debug_file;
485 node->line_no = _ft_debug_lineno;
486
487 node->cur_blocks = 0;
488 node->max_blocks = 0;
489 node->all_blocks = 0;
490
491 node->cur_size = 0;
492 node->max_size = 0;
493 node->all_size = 0;
494
495 node->cur_max = 0;
496
497 node->link = NULL;
498 node->hash = hash;
499 *pnode = node;
500
501 Exit:
502 return node;
503 }
504
505
506 static void
507 ft_mem_table_set( FT_MemTable table,
510 FT_Long delta )
511 {
512 FT_MemNode *pnode, node;
513
514
515 if ( table )
516 {
517 FT_MemSource source;
518
519
520 pnode = ft_mem_table_get_nodep( table, address );
521 node = *pnode;
522 if ( node )
523 {
524 if ( node->size < 0 )
525 {
526 /* This block was already freed. Our memory is now completely */
527 /* corrupted! */
528 /* This can only happen in keep-alive mode. */
529 ft_mem_debug_panic(
530 "memory heap corrupted (allocating freed block)" );
531 }
532 else
533 {
534 /* This block was already allocated. This means that our memory */
535 /* is also corrupted! */
536 ft_mem_debug_panic(
537 "memory heap corrupted (re-allocating allocated block at"
538 " %p, of size %ld)\n"
539 "org=%s:%d new=%s:%d\n",
540 node->address, node->size,
541 FT_FILENAME( node->source->file_name ), node->source->line_no,
542 FT_FILENAME( _ft_debug_file ), _ft_debug_lineno );
543 }
544 }
545
546 /* we need to create a new node in this table */
547 node = (FT_MemNode)ft_mem_table_alloc( table, sizeof ( *node ) );
548 if ( !node )
549 ft_mem_debug_panic( "not enough memory to run memory tests" );
550
551 node->address = address;
552 node->size = size;
553 node->source = source = ft_mem_table_get_source( table );
554
555 if ( delta == 0 )
556 {
557 /* this is an allocation */
558 source->all_blocks++;
559 source->cur_blocks++;
560 if ( source->cur_blocks > source->max_blocks )
561 source->max_blocks = source->cur_blocks;
562 }
563
564 if ( size > source->cur_max )
565 source->cur_max = size;
566
567 if ( delta != 0 )
568 {
569 /* we are growing or shrinking a reallocated block */
570 source->cur_size += delta;
571 table->alloc_current += delta;
572 }
573 else
574 {
575 /* we are allocating a new block */
576 source->cur_size += size;
577 table->alloc_current += size;
578 }
579
580 source->all_size += size;
581
582 if ( source->cur_size > source->max_size )
583 source->max_size = source->cur_size;
584
585 node->free_file_name = NULL;
586 node->free_line_no = 0;
587
588 node->link = pnode[0];
589
590 pnode[0] = node;
591 table->nodes++;
592
593 table->alloc_total += size;
594
595 if ( table->alloc_current > table->alloc_max )
596 table->alloc_max = table->alloc_current;
597
598 if ( table->nodes * 3 < table->size ||
599 table->size * 3 < table->nodes )
600 ft_mem_table_resize( table );
601 }
602 }
603
604
605 static void
606 ft_mem_table_remove( FT_MemTable table,
608 FT_Long delta )
609 {
610 if ( table )
611 {
612 FT_MemNode *pnode, node;
613
614
615 pnode = ft_mem_table_get_nodep( table, address );
616 node = *pnode;
617 if ( node )
618 {
619 FT_MemSource source;
620
621
622 if ( node->size < 0 )
623 ft_mem_debug_panic(
624 "freeing memory block at %p more than once\n"
625 " at (%s:%ld)!\n"
626 " Block was allocated at (%s:%ld)\n"
627 " and released at (%s:%ld).",
628 address,
629 FT_FILENAME( _ft_debug_file ), _ft_debug_lineno,
630 FT_FILENAME( node->source->file_name ), node->source->line_no,
631 FT_FILENAME( node->free_file_name ), node->free_line_no );
632
633 /* scramble the node's content for additional safety */
634 FT_MEM_SET( address, 0xF3, node->size );
635
636 if ( delta == 0 )
637 {
638 source = node->source;
639
640 source->cur_blocks--;
641 source->cur_size -= node->size;
642
643 table->alloc_current -= node->size;
644 }
645
646 if ( table->keep_alive )
647 {
648 /* we simply invert the node's size to indicate that the node */
649 /* was freed. */
650 node->size = -node->size;
651 node->free_file_name = _ft_debug_file;
652 node->free_line_no = _ft_debug_lineno;
653 }
654 else
655 {
656 table->nodes--;
657
658 *pnode = node->link;
659
660 node->size = 0;
661 node->source = NULL;
662
663 ft_mem_table_free( table, node );
664
665 if ( table->nodes * 3 < table->size ||
666 table->size * 3 < table->nodes )
667 ft_mem_table_resize( table );
668 }
669 }
670 else
671 ft_mem_debug_panic(
672 "trying to free unknown block at %p in (%s:%ld)\n",
673 address,
674 FT_FILENAME( _ft_debug_file ), _ft_debug_lineno );
675 }
676 }
677
678
679 static FT_Pointer
680 ft_mem_debug_alloc( FT_Memory memory,
681 FT_Long size )
682 {
683 FT_MemTable table = (FT_MemTable)memory->user;
684 FT_Byte* block;
685
686
687 if ( size <= 0 )
688 ft_mem_debug_panic( "negative block size allocation (%ld)", size );
689
690 /* return NULL if the maximum number of allocations was reached */
691 if ( table->bound_count &&
692 table->alloc_count >= table->alloc_count_max )
693 return NULL;
694
695 /* return NULL if this allocation would overflow the maximum heap size */
696 if ( table->bound_total &&
697 table->alloc_total_max - table->alloc_current > size )
698 return NULL;
699
700 block = (FT_Byte *)ft_mem_table_alloc( table, size );
701 if ( block )
702 {
703 ft_mem_table_set( table, block, size, 0 );
704
705 table->alloc_count++;
706 }
707
708 _ft_debug_file = "<unknown>";
709 _ft_debug_lineno = 0;
710
711 return (FT_Pointer)block;
712 }
713
714
715 static void
716 ft_mem_debug_free( FT_Memory memory,
718 {
719 FT_MemTable table = (FT_MemTable)memory->user;
720
721
722 if ( !block )
723 ft_mem_debug_panic( "trying to free NULL in (%s:%ld)",
724 FT_FILENAME( _ft_debug_file ),
725 _ft_debug_lineno );
726
727 ft_mem_table_remove( table, (FT_Byte*)block, 0 );
728
729 if ( !table->keep_alive )
730 ft_mem_table_free( table, block );
731
732 table->alloc_count--;
733
734 _ft_debug_file = "<unknown>";
735 _ft_debug_lineno = 0;
736 }
737
738
739 static FT_Pointer
740 ft_mem_debug_realloc( FT_Memory memory,
741 FT_Long cur_size,
744 {
745 FT_MemTable table = (FT_MemTable)memory->user;
746 FT_MemNode node, *pnode;
748 FT_Long delta;
749
750 const char* file_name = FT_FILENAME( _ft_debug_file );
751 FT_Long line_no = _ft_debug_lineno;
752
753
754 /* unlikely, but possible */
755 if ( new_size == cur_size )
756 return block;
757
758 /* the following is valid according to ANSI C */
759#if 0
760 if ( !block || !cur_size )
761 ft_mem_debug_panic( "trying to reallocate NULL in (%s:%ld)",
762 file_name, line_no );
763#endif
764
765 /* while the following is allowed in ANSI C also, we abort since */
766 /* such case should be handled by FreeType. */
767 if ( new_size <= 0 )
768 ft_mem_debug_panic(
769 "trying to reallocate %p to size 0 (current is %ld) in (%s:%ld)",
770 block, cur_size, file_name, line_no );
771
772 /* check `cur_size' value */
773 pnode = ft_mem_table_get_nodep( table, (FT_Byte*)block );
774 node = *pnode;
775 if ( !node )
776 ft_mem_debug_panic(
777 "trying to reallocate unknown block at %p in (%s:%ld)",
778 block, file_name, line_no );
779
780 if ( node->size <= 0 )
781 ft_mem_debug_panic(
782 "trying to reallocate freed block at %p in (%s:%ld)",
783 block, file_name, line_no );
784
785 if ( node->size != cur_size )
786 ft_mem_debug_panic( "invalid ft_realloc request for %p. cur_size is "
787 "%ld instead of %ld in (%s:%ld)",
788 block, cur_size, node->size, file_name, line_no );
789
790 /* return NULL if the maximum number of allocations was reached */
791 if ( table->bound_count &&
792 table->alloc_count >= table->alloc_count_max )
793 return NULL;
794
795 delta = new_size - cur_size;
796
797 /* return NULL if this allocation would overflow the maximum heap size */
798 if ( delta > 0 &&
799 table->bound_total &&
800 table->alloc_current + delta > table->alloc_total_max )
801 return NULL;
802
803 new_block = (FT_Pointer)ft_mem_table_alloc( table, new_size );
804 if ( !new_block )
805 return NULL;
806
807 ft_mem_table_set( table, (FT_Byte*)new_block, new_size, delta );
808
809 ft_memcpy( new_block, block, cur_size < new_size ? (size_t)cur_size
810 : (size_t)new_size );
811
812 ft_mem_table_remove( table, (FT_Byte*)block, delta );
813
814 _ft_debug_file = "<unknown>";
815 _ft_debug_lineno = 0;
816
817 if ( !table->keep_alive )
818 ft_mem_table_free( table, block );
819
820 return new_block;
821 }
822
823
824 extern FT_Int
825 ft_mem_debug_init( FT_Memory memory )
826 {
827 FT_MemTable table;
828 FT_Int result = 0;
829
830
831 if ( ft_getenv( "FT2_DEBUG_MEMORY" ) )
832 {
833 table = ft_mem_table_new( memory );
834 if ( table )
835 {
836 const char* p;
837
838
839 memory->user = table;
840 memory->alloc = ft_mem_debug_alloc;
841 memory->realloc = ft_mem_debug_realloc;
842 memory->free = ft_mem_debug_free;
843
844 p = ft_getenv( "FT2_ALLOC_TOTAL_MAX" );
845 if ( p )
846 {
847 FT_Long total_max = ft_strtol( p, NULL, 10 );
848
849
850 if ( total_max > 0 )
851 {
852 table->bound_total = 1;
853 table->alloc_total_max = total_max;
854 }
855 }
856
857 p = ft_getenv( "FT2_ALLOC_COUNT_MAX" );
858 if ( p )
859 {
860 FT_Long total_count = ft_strtol( p, NULL, 10 );
861
862
863 if ( total_count > 0 )
864 {
865 table->bound_count = 1;
866 table->alloc_count_max = total_count;
867 }
868 }
869
870 p = ft_getenv( "FT2_KEEP_ALIVE" );
871 if ( p )
872 {
873 FT_Long keep_alive = ft_strtol( p, NULL, 10 );
874
875
876 if ( keep_alive > 0 )
877 table->keep_alive = 1;
878 }
879
880 result = 1;
881 }
882 }
883 return result;
884 }
885
886
887 extern void
888 ft_mem_debug_done( FT_Memory memory )
889 {
890 FT_MemTable table = (FT_MemTable)memory->user;
891
892
893 if ( table )
894 {
895 memory->free = table->free;
896 memory->realloc = table->realloc;
897 memory->alloc = table->alloc;
898
899 ft_mem_table_destroy( table );
900 memory->user = NULL;
901 }
902 }
903
904
905 static int
906 ft_mem_source_compare( const void* p1,
907 const void* p2 )
908 {
909 FT_MemSource s1 = *(FT_MemSource*)p1;
910 FT_MemSource s2 = *(FT_MemSource*)p2;
911
912
913 if ( s2->max_size > s1->max_size )
914 return 1;
915 else if ( s2->max_size < s1->max_size )
916 return -1;
917 else
918 return 0;
919 }
920
921
922 extern void
923 FT_DumpMemory( FT_Memory memory )
924 {
925 FT_MemTable table = (FT_MemTable)memory->user;
926
927
928 if ( table )
929 {
930 FT_MemSource* bucket = table->sources;
931 FT_MemSource* limit = bucket + FT_MEM_SOURCE_BUCKETS;
932 FT_MemSource* sources;
933 FT_Int nn, count;
934 const char* fmt;
935
936
937 count = 0;
938 for ( ; bucket < limit; bucket++ )
939 {
940 FT_MemSource source = *bucket;
941
942
943 for ( ; source; source = source->link )
944 count++;
945 }
946
947 sources = (FT_MemSource*)
948 ft_mem_table_alloc(
949 table, count * (FT_Long)sizeof ( *sources ) );
950
951 count = 0;
952 for ( bucket = table->sources; bucket < limit; bucket++ )
953 {
954 FT_MemSource source = *bucket;
955
956
957 for ( ; source; source = source->link )
958 sources[count++] = source;
959 }
960
962 (size_t)count,
963 sizeof ( *sources ),
964 ft_mem_source_compare );
965
966 printf( "FreeType Memory Dump: "
967 "current=%ld max=%ld total=%ld count=%ld\n",
968 table->alloc_current, table->alloc_max,
969 table->alloc_total, table->alloc_count );
970 printf( " block block sizes sizes sizes source\n" );
971 printf( " count high sum highsum max location\n" );
972 printf( "-------------------------------------------------\n" );
973
974 fmt = "%6ld %6ld %8ld %8ld %8ld %s:%d\n";
975
976 for ( nn = 0; nn < count; nn++ )
977 {
978 FT_MemSource source = sources[nn];
979
980
981 printf( fmt,
982 source->cur_blocks, source->max_blocks,
983 source->cur_size, source->max_size, source->cur_max,
984 FT_FILENAME( source->file_name ),
985 source->line_no );
986 }
987 printf( "------------------------------------------------\n" );
988
989 ft_mem_table_free( table, sources );
990 }
991 }
992
993#else /* !FT_DEBUG_MEMORY */
994
995 /* ANSI C doesn't like empty source files */
996 typedef int _debug_mem_dummy;
997
998#endif /* !FT_DEBUG_MEMORY */
999
1000
1001/* END */
static INT max_size
Definition: history.c:51
#define FT_BASE_DEF(x)
const WCHAR * link
Definition: db.cpp:998
new_block
Definition: debug_heap.cpp:763
#define realloc
Definition: debug_ros.c:6
#define free
Definition: debug_ros.c:5
#define NULL
Definition: types.h:112
int CDECL vprintf(const char *format, va_list valist)
Definition: file.c:5517
#define va_end(v)
Definition: stdarg.h:28
#define va_start(v, l)
Definition: stdarg.h:26
char * va_list
Definition: vadefs.h:50
size_t const new_size
Definition: expand.cpp:66
#define printf
Definition: freeldr.h:104
int _debug_mem_dummy
Definition: ftdbgmem.c:996
#define FT_ZERO(p)
Definition: ftmemory.h:246
#define FT_ARRAY_ZERO(dest, count)
Definition: ftmemory.h:249
#define FT_MEM_SET(dest, byte, count)
Definition: ftmemory.h:234
#define ft_memcpy
Definition: ftstdlib.h:82
#define ft_strtol
Definition: ftstdlib.h:145
#define ft_getenv
Definition: ftstdlib.h:146
#define ft_qsort
Definition: ftstdlib.h:122
void *(* FT_Alloc_Func)(FT_Memory memory, long size)
Definition: ftsystem.h:87
typedefFT_BEGIN_HEADER struct FT_MemoryRec_ * FT_Memory
Definition: ftsystem.h:64
void *(* FT_Realloc_Func)(FT_Memory memory, long cur_size, long new_size, void *block)
Definition: ftsystem.h:141
void(* FT_Free_Func)(FT_Memory memory, void *block)
Definition: ftsystem.h:108
void * FT_Pointer
Definition: fttypes.h:310
FT_BEGIN_HEADER typedef unsigned char FT_Bool
Definition: fttypes.h:108
ft_ptrdiff_t FT_PtrDist
Definition: fttypes.h:336
unsigned char FT_Byte
Definition: fttypes.h:154
signed long FT_Long
Definition: fttypes.h:242
signed int FT_Int
Definition: fttypes.h:220
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLuint address
Definition: glext.h:9393
GLsizeiptr size
Definition: glext.h:5919
GLsizei GLenum * sources
Definition: glext.h:7753
GLint limit
Definition: glext.h:10326
GLuint64EXT * result
Definition: glext.h:11304
GLfloat GLfloat p
Definition: glext.h:8902
GLuint GLuint num
Definition: glext.h:9618
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define EXIT_FAILURE
Definition: jerror.c:33
if(dx< 0)
Definition: linetemp.h:194
struct S1 s1
static char memory[1024 *256]
Definition: process.c:122
static LPCWSTR file_name
Definition: protocol.c:147
long alloc_count
Definition: nc_alloc.cpp:36
static unsigned __int64 next
Definition: rand_nt.c:6
#define alloc
Definition: rosglue.h:13
#define exit(n)
Definition: config.h:202
struct list buckets
Definition: threadpool.c:324
PCWSTR s2
Definition: shell32_main.h:38
static void Exit(void)
Definition: sock.c:1330
Definition: dsound.c:943
Definition: _hash_fun.h:40
Definition: dlist.c:348
void int int ULONGLONG int va_list * ap
Definition: winesup.h:36
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList
static unsigned int block
Definition: xmlmemory.c:101