From fbff3e8fc75e891ced1d8350234bc9d8f21314b9 Mon Sep 17 00:00:00 2001 From: David Turner Date: Mon, 21 Feb 2000 16:18:25 +0000 Subject: [PATCH] added a memory checking test program, used to solve the memory leak reported by Jack Davis --- demos/src/memtest.c | 174 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 demos/src/memtest.c diff --git a/demos/src/memtest.c b/demos/src/memtest.c new file mode 100644 index 000000000..edf4189d5 --- /dev/null +++ b/demos/src/memtest.c @@ -0,0 +1,174 @@ +/* memtest.c */ + +#include +#include +#include +#include + + + 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; +} + + +