ReactOS  0.4.15-dev-3331-g8ebe441
ftdbgmem.c
Go to the documentation of this file.
1 /***************************************************************************/
2 /* */
3 /* ftdbgmem.c */
4 /* */
5 /* Memory debugger (body). */
6 /* */
7 /* Copyright 2001-2018 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
21 #include FT_INTERNAL_DEBUG_H
22 #include FT_INTERNAL_MEMORY_H
23 #include FT_SYSTEM_H
24 #include FT_ERRORS_H
25 #include FT_TYPES_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  {
114  FT_Long size;
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" );
221  exit( EXIT_FAILURE );
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,
243  FT_Pointer block )
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  {
257  FT_Long new_size;
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,
429  FT_Byte* address )
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,
508  FT_Byte* address,
509  FT_Long size,
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,
607  FT_Byte* address,
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 at (%s:%ld)\n"
625  "block allocated at (%s:%ld) and released at (%s:%ld)",
626  address,
627  FT_FILENAME( _ft_debug_file ), _ft_debug_lineno,
628  FT_FILENAME( node->source->file_name ), node->source->line_no,
629  FT_FILENAME( node->free_file_name ), node->free_line_no );
630 
631  /* scramble the node's content for additional safety */
632  FT_MEM_SET( address, 0xF3, node->size );
633 
634  if ( delta == 0 )
635  {
636  source = node->source;
637 
638  source->cur_blocks--;
639  source->cur_size -= node->size;
640 
641  table->alloc_current -= node->size;
642  }
643 
644  if ( table->keep_alive )
645  {
646  /* we simply invert the node's size to indicate that the node */
647  /* was freed. */
648  node->size = -node->size;
649  node->free_file_name = _ft_debug_file;
650  node->free_line_no = _ft_debug_lineno;
651  }
652  else
653  {
654  table->nodes--;
655 
656  *pnode = node->link;
657 
658  node->size = 0;
659  node->source = NULL;
660 
661  ft_mem_table_free( table, node );
662 
663  if ( table->nodes * 3 < table->size ||
664  table->size * 3 < table->nodes )
665  ft_mem_table_resize( table );
666  }
667  }
668  else
669  ft_mem_debug_panic(
670  "trying to free unknown block at %p in (%s:%ld)\n",
671  address,
672  FT_FILENAME( _ft_debug_file ), _ft_debug_lineno );
673  }
674  }
675 
676 
677  static FT_Pointer
678  ft_mem_debug_alloc( FT_Memory memory,
679  FT_Long size )
680  {
681  FT_MemTable table = (FT_MemTable)memory->user;
682  FT_Byte* block;
683 
684 
685  if ( size <= 0 )
686  ft_mem_debug_panic( "negative block size allocation (%ld)", size );
687 
688  /* return NULL if the maximum number of allocations was reached */
689  if ( table->bound_count &&
690  table->alloc_count >= table->alloc_count_max )
691  return NULL;
692 
693  /* return NULL if this allocation would overflow the maximum heap size */
694  if ( table->bound_total &&
695  table->alloc_total_max - table->alloc_current > size )
696  return NULL;
697 
698  block = (FT_Byte *)ft_mem_table_alloc( table, size );
699  if ( block )
700  {
701  ft_mem_table_set( table, block, size, 0 );
702 
703  table->alloc_count++;
704  }
705 
706  _ft_debug_file = "<unknown>";
707  _ft_debug_lineno = 0;
708 
709  return (FT_Pointer)block;
710  }
711 
712 
713  static void
714  ft_mem_debug_free( FT_Memory memory,
715  FT_Pointer block )
716  {
717  FT_MemTable table = (FT_MemTable)memory->user;
718 
719 
720  if ( !block )
721  ft_mem_debug_panic( "trying to free NULL in (%s:%ld)",
722  FT_FILENAME( _ft_debug_file ),
723  _ft_debug_lineno );
724 
725  ft_mem_table_remove( table, (FT_Byte*)block, 0 );
726 
727  if ( !table->keep_alive )
728  ft_mem_table_free( table, block );
729 
730  table->alloc_count--;
731 
732  _ft_debug_file = "<unknown>";
733  _ft_debug_lineno = 0;
734  }
735 
736 
737  static FT_Pointer
738  ft_mem_debug_realloc( FT_Memory memory,
739  FT_Long cur_size,
740  FT_Long new_size,
741  FT_Pointer block )
742  {
743  FT_MemTable table = (FT_MemTable)memory->user;
744  FT_MemNode node, *pnode;
745  FT_Pointer new_block;
746  FT_Long delta;
747 
748  const char* file_name = FT_FILENAME( _ft_debug_file );
749  FT_Long line_no = _ft_debug_lineno;
750 
751 
752  /* unlikely, but possible */
753  if ( new_size == cur_size )
754  return block;
755 
756  /* the following is valid according to ANSI C */
757 #if 0
758  if ( !block || !cur_size )
759  ft_mem_debug_panic( "trying to reallocate NULL in (%s:%ld)",
760  file_name, line_no );
761 #endif
762 
763  /* while the following is allowed in ANSI C also, we abort since */
764  /* such case should be handled by FreeType. */
765  if ( new_size <= 0 )
766  ft_mem_debug_panic(
767  "trying to reallocate %p to size 0 (current is %ld) in (%s:%ld)",
768  block, cur_size, file_name, line_no );
769 
770  /* check `cur_size' value */
771  pnode = ft_mem_table_get_nodep( table, (FT_Byte*)block );
772  node = *pnode;
773  if ( !node )
774  ft_mem_debug_panic(
775  "trying to reallocate unknown block at %p in (%s:%ld)",
776  block, file_name, line_no );
777 
778  if ( node->size <= 0 )
779  ft_mem_debug_panic(
780  "trying to reallocate freed block at %p in (%s:%ld)",
781  block, file_name, line_no );
782 
783  if ( node->size != cur_size )
784  ft_mem_debug_panic( "invalid ft_realloc request for %p. cur_size is "
785  "%ld instead of %ld in (%s:%ld)",
786  block, cur_size, node->size, file_name, line_no );
787 
788  /* return NULL if the maximum number of allocations was reached */
789  if ( table->bound_count &&
790  table->alloc_count >= table->alloc_count_max )
791  return NULL;
792 
793  delta = new_size - cur_size;
794 
795  /* return NULL if this allocation would overflow the maximum heap size */
796  if ( delta > 0 &&
797  table->bound_total &&
798  table->alloc_current + delta > table->alloc_total_max )
799  return NULL;
800 
801  new_block = (FT_Pointer)ft_mem_table_alloc( table, new_size );
802  if ( !new_block )
803  return NULL;
804 
805  ft_mem_table_set( table, (FT_Byte*)new_block, new_size, delta );
806 
807  ft_memcpy( new_block, block, cur_size < new_size ? (size_t)cur_size
808  : (size_t)new_size );
809 
810  ft_mem_table_remove( table, (FT_Byte*)block, delta );
811 
812  _ft_debug_file = "<unknown>";
813  _ft_debug_lineno = 0;
814 
815  if ( !table->keep_alive )
816  ft_mem_table_free( table, block );
817 
818  return new_block;
819  }
820 
821 
822  extern FT_Int
823  ft_mem_debug_init( FT_Memory memory )
824  {
825  FT_MemTable table;
826  FT_Int result = 0;
827 
828 
829  if ( ft_getenv( "FT2_DEBUG_MEMORY" ) )
830  {
831  table = ft_mem_table_new( memory );
832  if ( table )
833  {
834  const char* p;
835 
836 
837  memory->user = table;
838  memory->alloc = ft_mem_debug_alloc;
839  memory->realloc = ft_mem_debug_realloc;
840  memory->free = ft_mem_debug_free;
841 
842  p = ft_getenv( "FT2_ALLOC_TOTAL_MAX" );
843  if ( p )
844  {
845  FT_Long total_max = ft_strtol( p, NULL, 10 );
846 
847 
848  if ( total_max > 0 )
849  {
850  table->bound_total = 1;
851  table->alloc_total_max = total_max;
852  }
853  }
854 
855  p = ft_getenv( "FT2_ALLOC_COUNT_MAX" );
856  if ( p )
857  {
858  FT_Long total_count = ft_strtol( p, NULL, 10 );
859 
860 
861  if ( total_count > 0 )
862  {
863  table->bound_count = 1;
864  table->alloc_count_max = total_count;
865  }
866  }
867 
868  p = ft_getenv( "FT2_KEEP_ALIVE" );
869  if ( p )
870  {
871  FT_Long keep_alive = ft_strtol( p, NULL, 10 );
872 
873 
874  if ( keep_alive > 0 )
875  table->keep_alive = 1;
876  }
877 
878  result = 1;
879  }
880  }
881  return result;
882  }
883 
884 
885  extern void
886  ft_mem_debug_done( FT_Memory memory )
887  {
888  FT_MemTable table = (FT_MemTable)memory->user;
889 
890 
891  if ( table )
892  {
893  memory->free = table->free;
894  memory->realloc = table->realloc;
895  memory->alloc = table->alloc;
896 
897  ft_mem_table_destroy( table );
898  memory->user = NULL;
899  }
900  }
901 
902 
903  static int
904  ft_mem_source_compare( const void* p1,
905  const void* p2 )
906  {
907  FT_MemSource s1 = *(FT_MemSource*)p1;
908  FT_MemSource s2 = *(FT_MemSource*)p2;
909 
910 
911  if ( s2->max_size > s1->max_size )
912  return 1;
913  else if ( s2->max_size < s1->max_size )
914  return -1;
915  else
916  return 0;
917  }
918 
919 
920  extern void
921  FT_DumpMemory( FT_Memory memory )
922  {
923  FT_MemTable table = (FT_MemTable)memory->user;
924 
925 
926  if ( table )
927  {
928  FT_MemSource* bucket = table->sources;
929  FT_MemSource* limit = bucket + FT_MEM_SOURCE_BUCKETS;
930  FT_MemSource* sources;
931  FT_Int nn, count;
932  const char* fmt;
933 
934 
935  count = 0;
936  for ( ; bucket < limit; bucket++ )
937  {
938  FT_MemSource source = *bucket;
939 
940 
941  for ( ; source; source = source->link )
942  count++;
943  }
944 
945  sources = (FT_MemSource*)
946  ft_mem_table_alloc(
947  table, count * (FT_Long)sizeof ( *sources ) );
948 
949  count = 0;
950  for ( bucket = table->sources; bucket < limit; bucket++ )
951  {
952  FT_MemSource source = *bucket;
953 
954 
955  for ( ; source; source = source->link )
956  sources[count++] = source;
957  }
958 
959  ft_qsort( sources,
960  (size_t)count,
961  sizeof ( *sources ),
962  ft_mem_source_compare );
963 
964  printf( "FreeType Memory Dump: "
965  "current=%ld max=%ld total=%ld count=%ld\n",
966  table->alloc_current, table->alloc_max,
967  table->alloc_total, table->alloc_count );
968  printf( " block block sizes sizes sizes source\n" );
969  printf( " count high sum highsum max location\n" );
970  printf( "-------------------------------------------------\n" );
971 
972  fmt = "%6ld %6ld %8ld %8ld %8ld %s:%d\n";
973 
974  for ( nn = 0; nn < count; nn++ )
975  {
976  FT_MemSource source = sources[nn];
977 
978 
979  printf( fmt,
980  source->cur_blocks, source->max_blocks,
981  source->cur_size, source->max_size, source->cur_max,
982  FT_FILENAME( source->file_name ),
983  source->line_no );
984  }
985  printf( "------------------------------------------------\n" );
986 
987  ft_mem_table_free( table, sources );
988  }
989  }
990 
991 #else /* !FT_DEBUG_MEMORY */
992 
993  /* ANSI C doesn't like empty source files */
994  typedef int _debug_mem_dummy;
995 
996 #endif /* !FT_DEBUG_MEMORY */
997 
998 
999 /* END */
#define realloc
Definition: debug_ros.c:6
static unsigned int block
Definition: xmlmemory.c:118
ft_ptrdiff_t FT_PtrDist
Definition: fttypes.h:337
struct S2 s2
signed long FT_Long
Definition: fttypes.h:242
GLuint64EXT * result
Definition: glext.h:11304
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList
#define FT_ARRAY_ZERO(dest, count)
Definition: ftmemory.h:240
signed int FT_Int
Definition: fttypes.h:220
GLuint GLuint GLsizei count
Definition: gl.h:1545
#define free
Definition: debug_ros.c:5
const char * fmt
Definition: wsprintf.c:30
GLenum GLsizei GLenum GLenum const GLvoid * table
Definition: glext.h:5644
if(dx==0 &&dy==0)
Definition: linetemp.h:174
void *(* FT_Realloc_Func)(FT_Memory memory, long cur_size, long new_size, void *block)
Definition: ftsystem.h:143
static char memory[1024 *256]
Definition: process.c:116
int _debug_mem_dummy
Definition: ftdbgmem.c:994
GLint limit
Definition: glext.h:10326
FT_BEGIN_HEADER typedef unsigned char FT_Bool
Definition: fttypes.h:108
struct node node
#define ft_qsort
Definition: ftstdlib.h:122
#define va_end(ap)
Definition: acmsvcex.h:90
int hash
Definition: main.c:58
unsigned char FT_Byte
Definition: fttypes.h:154
static INT max_size
Definition: history.c:51
GLsizei GLenum * sources
Definition: glext.h:7753
char * va_list
Definition: acmsvcex.h:78
void(* FT_Free_Func)(FT_Memory memory, void *block)
Definition: ftsystem.h:110
GLsizeiptr size
Definition: glext.h:5919
void * FT_Pointer
Definition: fttypes.h:311
#define FT_ZERO(p)
Definition: ftmemory.h:237
_Check_return_opt_ _CRTIMP int __cdecl vprintf(_In_z_ _Printf_format_string_ const char *_Format, va_list _ArgList)
struct S1 s1
static void Exit(void)
Definition: sock.c:1331
GLuint address
Definition: glext.h:9393
GLuint GLuint num
Definition: glext.h:9618
va_start(ap, x)
#define EXIT_FAILURE
Definition: jerror.c:33
long alloc_count
Definition: nc_alloc.cpp:36
void *(* FT_Alloc_Func)(FT_Memory memory, long size)
Definition: ftsystem.h:89
#define ft_getenv
Definition: ftstdlib.h:146
typedefFT_BEGIN_HEADER struct FT_MemoryRec_ * FT_Memory
Definition: ftsystem.h:66
static unsigned __int64 next
Definition: rand_nt.c:6
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
GLsizei GLsizei GLchar * source
Definition: glext.h:6048
#define alloc
Definition: rosglue.h:13
#define NULL
Definition: types.h:112
#define FT_BASE_DEF(x)
Definition: ftconfig.h:419
static LPCWSTR file_name
Definition: protocol.c:147
void int int ULONGLONG int va_list * ap
Definition: winesup.h:32
const WCHAR * link
Definition: db.cpp:991
#define FT_MEM_SET(dest, byte, count)
Definition: ftmemory.h:225
void exit(int exitcode)
Definition: _exit.c:33
GLfloat GLfloat p
Definition: glext.h:8902
Definition: _hash_fun.h:40
#define ft_memcpy
Definition: ftstdlib.h:82
Definition: dsound.c:943
#define ft_strtol
Definition: ftstdlib.h:145
#define printf
Definition: config.h:203
Definition: dlist.c:348