ref: fbff3e8fc75e891ced1d8350234bc9d8f21314b9
parent: c64f644264cc3955daefc1dcc99f3a610b48850b
author: David Turner <[email protected]>
date: Mon Feb 21 11:18:25 EST 2000
added a memory checking test program, used to solve the memory leak reported by Jack Davis
--- /dev/null
+++ b/demos/src/memtest.c
@@ -1,0 +1,174 @@
+/* memtest.c */
+
+#include <freetype.h>
+#include <ftobjs.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+ EXPORT_DEF
+ void FT_Default_Drivers( FT_Library library );
+
+
+/* Our own memory allocator. To check that a single block isn't freed */
+/* several time, we simply do not call "free".. */
+
+
+#define MAX_RECORDED_BLOCKS 4096
+#define CHECK_DUPLICATES
+
+typedef struct MyBlock
+{
+ void* base;
+ long size;
+
+} MyBlock;
+
+static MyBlock my_blocks[ MAX_RECORDED_BLOCKS ];
+static int num_my_blocks = 0;
+
+/* record a new block in the table, check for duplicates too */
+static
+void record_my_block( void* base, long size )
+{
+ if (size <= 0)
+ {
+ fprintf( stderr, "adding a block with non-positive length - should not happen \n" );
+ exit(1);
+ }
+
+ if ( num_my_blocks < MAX_RECORDED_BLOCKS )
+ {
+ MyBlock* block;
+
+#ifdef CHECK_DUPLICATES
+ MyBlock* limit;
+ block = my_blocks;
+ limit = block + num_my_blocks;
+ for ( ; block < limit; block++ )
+ {
+ if ( block->base == base && block->size != 0 )
+ {
+ fprintf( stderr, "duplicate memory block at %08lx\n", (long)block->base );
+ exit(1);
+ }
+ }
+#endif
+
+ block = my_blocks + num_my_blocks++;
+ block->base = base;
+ block->size = size;
+ }
+ else
+ {
+ fprintf( stderr, "Too many memory blocks -- test exited !!\n" );
+ exit(1);
+ }
+}
+
+/* forget a block, and check that it isn't part of our table already */
+static
+void forget_my_block( void* base )
+{
+ MyBlock* block = my_blocks + num_my_blocks-1;
+
+ /* we scan in reverse, because transient blocks are always located */
+ /* at the end of the table.. (it supposedly faster then..) */
+ for ( ; block >= my_blocks; block-- )
+ {
+ if ( block->base == base )
+ {
+ if (block->size > 0)
+ {
+ block->size = 0;
+ return;
+ }
+ else
+ {
+ fprintf( stderr, "Block at %08lx released twice \n", (long)base );
+ exit(1);
+ }
+ }
+ }
+ fprintf( stderr, "Trying to release an unallocated block at %08lx\n",
+ (long)base );
+ exit(1);
+}
+
+
+static
+void* my_alloc( FT_Memory memory,
+ long size )
+{
+ void* p = malloc(size);
+ if (p)
+ record_my_block(p,size);
+
+ return p;
+}
+
+static
+void my_free( FT_Memory memory, void* block )
+{
+ forget_my_block(block);
+ free(block);
+}
+
+static
+void* my_realloc( FT_Memory memory,
+ long cur_size,
+ long new_size,
+ void* block )
+{
+ void* p;
+
+ p = my_alloc( memory, new_size );
+ if (p)
+ {
+ my_free( memory, block );
+ record_my_block( p, new_size );
+ }
+ return p;
+}
+
+
+struct FT_MemoryRec_ my_memory =
+{
+ 0,
+ my_alloc,
+ my_free,
+ my_realloc
+};
+
+
+int main( void )
+{
+ FT_Library library;
+ FT_Face face;
+ int glyphIndex;
+ int result;
+
+ /* Create a new library with our own memory manager */
+ result = FT_New_Library( &my_memory, &library );
+
+ /* the new library has no drivers in it, add the default ones */
+ /* (implemented in ftinit.c).. */
+ FT_Default_Drivers(library);
+
+ result = FT_New_Face( library, "d:/ttf/arial.ttf", 0, &face );
+ result = FT_Set_Char_Size( face, 0, 16*64, 96, 96 );
+
+ glyphIndex = FT_Get_Char_Index( face, (int)'A' );
+
+ /* memory error occurs in FT_DoneFreeType() if FT_Load_Glyph() is called */
+ result = FT_Load_Glyph(face, glyphIndex, FT_LOAD_DEFAULT );
+
+ result = FT_Done_Face( face );
+
+ result = FT_Done_FreeType( library );
+
+ return 0;
+}
+
+
+