2001-12-05 02:22:05 +01:00
|
|
|
/***************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* ftdbgmem.c */
|
|
|
|
/* */
|
|
|
|
/* Memory debugger (body). */
|
|
|
|
/* */
|
|
|
|
/* Copyright 2001 by */
|
|
|
|
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
|
|
|
|
/* */
|
|
|
|
/* This file is part of the FreeType project, and may only be used, */
|
|
|
|
/* modified, and distributed under the terms of the FreeType project */
|
|
|
|
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
|
|
|
|
/* this file you indicate that you have read the license and */
|
|
|
|
/* understand and accept it fully. */
|
|
|
|
/* */
|
|
|
|
/***************************************************************************/
|
|
|
|
|
|
|
|
|
2001-10-22 10:32:21 +02:00
|
|
|
#include <ft2build.h>
|
|
|
|
#include FT_CONFIG_CONFIG_H
|
|
|
|
#include FT_INTERNAL_DEBUG_H
|
2001-10-26 18:58:27 +02:00
|
|
|
#include FT_INTERNAL_MEMORY_H
|
2001-10-22 10:32:21 +02:00
|
|
|
#include FT_SYSTEM_H
|
|
|
|
#include FT_ERRORS_H
|
|
|
|
#include FT_TYPES_H
|
|
|
|
|
2001-12-05 02:22:05 +01:00
|
|
|
|
2001-10-22 10:32:21 +02:00
|
|
|
#ifdef FT_DEBUG_MEMORY
|
|
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct FT_MemNodeRec_* FT_MemNode;
|
|
|
|
typedef struct FT_MemTableRec_* FT_MemTable;
|
|
|
|
|
2001-12-05 02:22:05 +01:00
|
|
|
#define FT_MEM_VAL( addr ) ((FT_ULong)(FT_Pointer)( addr ))
|
2001-10-22 10:32:21 +02:00
|
|
|
|
2001-12-05 02:22:05 +01:00
|
|
|
typedef struct FT_MemNodeRec_
|
2001-10-22 10:32:21 +02:00
|
|
|
{
|
2001-10-22 16:50:41 +02:00
|
|
|
FT_Byte* address;
|
|
|
|
FT_Long size; /* < 0 if the block was freed */
|
2001-12-05 02:22:05 +01:00
|
|
|
|
|
|
|
const char* alloc_file_name;
|
2001-10-24 10:04:00 +02:00
|
|
|
FT_Long alloc_line_no;
|
2001-12-05 02:22:05 +01:00
|
|
|
|
|
|
|
const char* free_file_name;
|
2001-10-24 10:04:00 +02:00
|
|
|
FT_Long free_line_no;
|
2001-10-22 16:50:41 +02:00
|
|
|
|
|
|
|
FT_MemNode link;
|
2001-10-22 10:32:21 +02:00
|
|
|
|
2001-12-05 02:22:05 +01:00
|
|
|
} FT_MemNodeRec;
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct FT_MemTableRec_
|
2001-10-22 10:32:21 +02:00
|
|
|
{
|
2001-12-05 02:22:05 +01:00
|
|
|
FT_ULong size;
|
|
|
|
FT_ULong nodes;
|
|
|
|
FT_MemNode* buckets;
|
2001-10-22 10:32:21 +02:00
|
|
|
|
2001-12-05 02:22:05 +01:00
|
|
|
FT_ULong alloc_total;
|
|
|
|
FT_ULong alloc_current;
|
|
|
|
FT_ULong alloc_max;
|
2001-10-24 09:32:55 +02:00
|
|
|
|
2001-12-05 02:22:05 +01:00
|
|
|
const char* file_name;
|
|
|
|
FT_Long line_no;
|
|
|
|
|
|
|
|
FT_Memory memory;
|
|
|
|
FT_Pointer memory_user;
|
2001-10-24 09:32:55 +02:00
|
|
|
FT_Alloc_Func alloc;
|
|
|
|
FT_Free_Func free;
|
|
|
|
FT_Realloc_Func realloc;
|
2001-10-22 10:32:21 +02:00
|
|
|
|
2001-12-05 02:22:05 +01:00
|
|
|
} FT_MemTableRec;
|
|
|
|
|
|
|
|
|
|
|
|
#define FT_MEM_SIZE_MIN 7
|
|
|
|
#define FT_MEM_SIZE_MAX 13845163
|
|
|
|
|
|
|
|
#define FT_FILENAME( x ) ((x) ? (x) : "unknown file")
|
2001-10-22 10:32:21 +02:00
|
|
|
|
2001-10-24 10:04:00 +02:00
|
|
|
|
2001-10-22 10:32:21 +02:00
|
|
|
static const FT_UInt ft_mem_primes[] =
|
|
|
|
{
|
|
|
|
7,
|
|
|
|
11,
|
|
|
|
19,
|
|
|
|
37,
|
|
|
|
73,
|
|
|
|
109,
|
|
|
|
163,
|
|
|
|
251,
|
|
|
|
367,
|
|
|
|
557,
|
|
|
|
823,
|
|
|
|
1237,
|
|
|
|
1861,
|
|
|
|
2777,
|
|
|
|
4177,
|
|
|
|
6247,
|
|
|
|
9371,
|
|
|
|
14057,
|
|
|
|
21089,
|
|
|
|
31627,
|
|
|
|
47431,
|
|
|
|
71143,
|
|
|
|
106721,
|
|
|
|
160073,
|
|
|
|
240101,
|
|
|
|
360163,
|
|
|
|
540217,
|
|
|
|
810343,
|
|
|
|
1215497,
|
|
|
|
1823231,
|
|
|
|
2734867,
|
|
|
|
4102283,
|
|
|
|
6153409,
|
|
|
|
9230113,
|
|
|
|
13845163,
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
|
|
|
|
|
|
|
extern void
|
|
|
|
ft_mem_debug_panic( const char* fmt, ... )
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
|
2001-10-24 10:04:00 +02:00
|
|
|
printf( "FreeType.Debug: " );
|
2001-10-22 10:32:21 +02:00
|
|
|
|
|
|
|
va_start( ap, fmt );
|
|
|
|
vprintf( fmt, ap );
|
|
|
|
va_end( ap );
|
|
|
|
|
|
|
|
printf( "\n" );
|
|
|
|
exit( EXIT_FAILURE );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static FT_ULong
|
|
|
|
ft_mem_closest_prime( FT_ULong num )
|
|
|
|
{
|
|
|
|
FT_UInt i;
|
|
|
|
|
2001-12-05 02:22:05 +01:00
|
|
|
|
|
|
|
for ( i = 0;
|
|
|
|
i < sizeof ( ft_mem_primes ) / sizeof ( ft_mem_primes[0] ); i++ )
|
2001-10-22 10:32:21 +02:00
|
|
|
if ( ft_mem_primes[i] > num )
|
|
|
|
return ft_mem_primes[i];
|
|
|
|
|
|
|
|
return FT_MEM_SIZE_MAX;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-10-24 09:32:55 +02:00
|
|
|
static FT_Pointer
|
|
|
|
ft_mem_table_alloc( FT_MemTable table,
|
|
|
|
FT_Long size )
|
|
|
|
{
|
|
|
|
FT_Memory memory = table->memory;
|
|
|
|
FT_Pointer block;
|
|
|
|
|
2001-12-05 02:22:05 +01:00
|
|
|
|
2001-10-24 09:32:55 +02:00
|
|
|
memory->user = table->memory_user;
|
|
|
|
block = table->alloc( memory, size );
|
|
|
|
memory->user = table;
|
2001-12-05 02:22:05 +01:00
|
|
|
|
|
|
|
return block;
|
2001-10-24 09:32:55 +02:00
|
|
|
}
|
|
|
|
|
2001-12-05 02:22:05 +01:00
|
|
|
|
2001-10-24 09:32:55 +02:00
|
|
|
static void
|
|
|
|
ft_mem_table_free( FT_MemTable table,
|
|
|
|
FT_Pointer block )
|
|
|
|
{
|
|
|
|
FT_Memory memory = table->memory;
|
|
|
|
|
2001-12-05 02:22:05 +01:00
|
|
|
|
2001-10-24 09:32:55 +02:00
|
|
|
memory->user = table->memory_user;
|
|
|
|
table->free( memory, block );
|
|
|
|
memory->user = table;
|
|
|
|
}
|
|
|
|
|
2001-10-22 10:32:21 +02:00
|
|
|
|
|
|
|
static void
|
|
|
|
ft_mem_table_resize( FT_MemTable table )
|
|
|
|
{
|
|
|
|
FT_ULong new_size;
|
|
|
|
|
2001-12-05 02:22:05 +01:00
|
|
|
|
2001-10-22 10:32:21 +02:00
|
|
|
new_size = ft_mem_closest_prime( table->nodes );
|
2001-12-05 02:22:05 +01:00
|
|
|
if ( new_size != table->size )
|
2001-10-22 10:32:21 +02:00
|
|
|
{
|
|
|
|
FT_MemNode* new_buckets ;
|
|
|
|
FT_ULong i;
|
|
|
|
|
2001-12-05 02:22:05 +01:00
|
|
|
|
|
|
|
new_buckets = ft_mem_table_alloc( table,
|
|
|
|
new_size * sizeof ( FT_MemNode ) );
|
2001-10-22 10:32:21 +02:00
|
|
|
if ( new_buckets == NULL )
|
|
|
|
return;
|
2001-12-05 02:22:05 +01:00
|
|
|
|
|
|
|
MEM_Set( new_buckets, 0, sizeof ( FT_MemNode ) * new_size );
|
|
|
|
|
2001-10-22 10:32:21 +02:00
|
|
|
for ( i = 0; i < table->size; i++ )
|
|
|
|
{
|
|
|
|
FT_MemNode node, next, *pnode;
|
|
|
|
FT_ULong hash;
|
|
|
|
|
2001-12-05 02:22:05 +01:00
|
|
|
|
2001-10-22 10:32:21 +02:00
|
|
|
node = table->buckets[i];
|
2001-12-05 02:22:05 +01:00
|
|
|
while ( node )
|
2001-10-22 10:32:21 +02:00
|
|
|
{
|
|
|
|
next = node->link;
|
2001-12-05 02:22:05 +01:00
|
|
|
hash = FT_MEM_VAL( node->address ) % new_size;
|
2001-10-22 10:32:21 +02:00
|
|
|
pnode = new_buckets + hash;
|
|
|
|
|
|
|
|
node->link = pnode[0];
|
|
|
|
pnode[0] = node;
|
|
|
|
|
2001-12-05 02:22:05 +01:00
|
|
|
node = next;
|
2001-10-22 10:32:21 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( table->buckets )
|
2001-10-24 09:32:55 +02:00
|
|
|
ft_mem_table_free( table, table->buckets );
|
2001-12-05 02:22:05 +01:00
|
|
|
|
2001-10-22 10:32:21 +02:00
|
|
|
table->buckets = new_buckets;
|
|
|
|
table->size = new_size;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static FT_MemTable
|
2001-10-24 09:32:55 +02:00
|
|
|
ft_mem_table_new( FT_Memory memory )
|
2001-10-22 10:32:21 +02:00
|
|
|
{
|
|
|
|
FT_MemTable table;
|
|
|
|
|
2001-12-05 02:22:05 +01:00
|
|
|
|
|
|
|
table = memory->alloc( memory, sizeof ( *table ) );
|
|
|
|
if ( table == NULL )
|
|
|
|
goto Exit;
|
|
|
|
|
|
|
|
MEM_Set( table, 0, sizeof ( *table ) );
|
2001-10-22 10:32:21 +02:00
|
|
|
|
|
|
|
table->size = FT_MEM_SIZE_MIN;
|
|
|
|
table->nodes = 0;
|
2001-12-05 02:22:05 +01:00
|
|
|
|
|
|
|
table->memory = memory;
|
2001-10-22 10:32:21 +02:00
|
|
|
|
2001-10-24 09:32:55 +02:00
|
|
|
table->memory_user = memory->user;
|
2001-12-05 02:22:05 +01:00
|
|
|
|
2001-10-24 09:32:55 +02:00
|
|
|
table->alloc = memory->alloc;
|
|
|
|
table->realloc = memory->realloc;
|
|
|
|
table->free = memory->free;
|
|
|
|
|
2001-12-05 02:22:05 +01:00
|
|
|
table->buckets = memory->alloc( memory,
|
|
|
|
table->size * sizeof ( FT_MemNode ) );
|
2001-10-22 10:32:21 +02:00
|
|
|
if ( table->buckets )
|
2001-12-05 02:22:05 +01:00
|
|
|
MEM_Set( table->buckets, 0, sizeof ( FT_MemNode ) * table->size );
|
2001-10-22 10:32:21 +02:00
|
|
|
else
|
|
|
|
{
|
2001-10-24 09:32:55 +02:00
|
|
|
memory->free( memory, table );
|
2001-10-22 10:32:21 +02:00
|
|
|
table = NULL;
|
|
|
|
}
|
2001-12-05 02:22:05 +01:00
|
|
|
|
|
|
|
Exit:
|
2001-10-22 10:32:21 +02:00
|
|
|
return table;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
ft_mem_table_destroy( FT_MemTable table )
|
|
|
|
{
|
2001-12-05 02:22:05 +01:00
|
|
|
FT_ULong i;
|
|
|
|
|
2001-10-22 10:32:21 +02:00
|
|
|
|
|
|
|
if ( table )
|
|
|
|
{
|
2001-10-24 09:32:55 +02:00
|
|
|
FT_Long leak_count = 0;
|
|
|
|
FT_ULong leaks = 0;
|
2001-12-05 02:22:05 +01:00
|
|
|
|
|
|
|
|
2001-10-22 10:32:21 +02:00
|
|
|
for ( i = 0; i < table->size; i++ )
|
|
|
|
{
|
|
|
|
FT_MemNode *pnode = table->buckets + i, next, node = *pnode;
|
|
|
|
|
2001-12-05 02:22:05 +01:00
|
|
|
|
|
|
|
while ( node )
|
2001-10-22 10:32:21 +02:00
|
|
|
{
|
2001-12-05 02:22:05 +01:00
|
|
|
next = node->link;
|
|
|
|
node->link = 0;
|
|
|
|
|
2001-10-22 10:32:21 +02:00
|
|
|
if ( node->size > 0 )
|
|
|
|
{
|
2001-12-05 02:22:05 +01:00
|
|
|
printf(
|
|
|
|
"leaked memory block at address %p, size %8ld in (%s:%ld)\n",
|
|
|
|
node->address, node->size,
|
|
|
|
FT_FILENAME( node->alloc_file_name ),
|
|
|
|
node->alloc_line_no );
|
|
|
|
|
2001-10-22 10:32:21 +02:00
|
|
|
leak_count++;
|
|
|
|
leaks += node->size;
|
2001-12-05 02:22:05 +01:00
|
|
|
|
2001-10-24 09:32:55 +02:00
|
|
|
ft_mem_table_free( table, node->address );
|
2001-10-22 10:32:21 +02:00
|
|
|
}
|
2001-12-05 02:22:05 +01:00
|
|
|
|
2001-10-22 10:32:21 +02:00
|
|
|
node->address = NULL;
|
|
|
|
node->size = 0;
|
2001-12-05 02:22:05 +01:00
|
|
|
|
2001-10-22 10:32:21 +02:00
|
|
|
free( node );
|
|
|
|
node = next;
|
|
|
|
}
|
|
|
|
table->buckets[i] = 0;
|
|
|
|
}
|
2001-10-24 09:32:55 +02:00
|
|
|
ft_mem_table_free( table, table->buckets );
|
2001-10-22 10:32:21 +02:00
|
|
|
table->buckets = NULL;
|
|
|
|
|
|
|
|
table->size = 0;
|
|
|
|
table->nodes = 0;
|
|
|
|
free( table );
|
2001-10-22 22:15:29 +02:00
|
|
|
|
2001-12-05 02:22:05 +01:00
|
|
|
printf(
|
|
|
|
"FreeType: total memory allocations = %ld\n", table->alloc_total );
|
|
|
|
printf(
|
|
|
|
"FreeType: maximum memory footprint = %ld\n", table->alloc_max );
|
|
|
|
|
2001-10-22 10:32:21 +02:00
|
|
|
if ( leak_count > 0 )
|
2001-12-05 02:22:05 +01:00
|
|
|
ft_mem_debug_panic(
|
|
|
|
"FreeType: %ld bytes of memory leaked in %ld blocks\n",
|
|
|
|
leaks, leak_count );
|
|
|
|
printf( "FreeType: No memory leaks detected!\n" );
|
2001-10-22 10:32:21 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static FT_MemNode*
|
|
|
|
ft_mem_table_get_nodep( FT_MemTable table,
|
2001-12-05 02:22:05 +01:00
|
|
|
FT_Byte* address )
|
2001-10-22 10:32:21 +02:00
|
|
|
{
|
2001-12-05 02:22:05 +01:00
|
|
|
FT_ULong hash;
|
|
|
|
FT_MemNode *pnode, node;
|
2001-10-22 10:32:21 +02:00
|
|
|
|
2001-12-05 02:22:05 +01:00
|
|
|
|
|
|
|
hash = FT_MEM_VAL( address );
|
|
|
|
pnode = table->buckets + ( hash % table->size );
|
2001-10-22 10:32:21 +02:00
|
|
|
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
node = pnode[0];
|
2001-12-05 02:22:05 +01:00
|
|
|
if ( !node )
|
2001-10-22 10:32:21 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
if ( node->address == address )
|
|
|
|
break;
|
|
|
|
|
|
|
|
pnode = &node->link;
|
|
|
|
}
|
|
|
|
return pnode;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
ft_mem_table_set( FT_MemTable table,
|
|
|
|
FT_Byte* address,
|
|
|
|
FT_ULong size )
|
|
|
|
{
|
|
|
|
FT_MemNode *pnode, node;
|
|
|
|
|
2001-12-05 02:22:05 +01:00
|
|
|
|
|
|
|
if ( table )
|
2001-10-22 10:32:21 +02:00
|
|
|
{
|
|
|
|
pnode = ft_mem_table_get_nodep( table, address );
|
|
|
|
node = *pnode;
|
2001-12-05 02:22:05 +01:00
|
|
|
if ( node )
|
2001-10-22 10:32:21 +02:00
|
|
|
{
|
|
|
|
if ( node->size < 0 )
|
|
|
|
{
|
2001-12-05 02:22:05 +01:00
|
|
|
/* this block was already freed. This means that our memory is */
|
|
|
|
/* now completely corrupted! */
|
|
|
|
ft_mem_debug_panic(
|
|
|
|
"memory heap corrupted (allocating freed block)" );
|
2001-10-22 10:32:21 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2001-12-05 02:22:05 +01:00
|
|
|
/* this block was already allocated. This means that our memory */
|
|
|
|
/* is also corrupted! */
|
|
|
|
ft_mem_debug_panic(
|
|
|
|
"memory heap corrupted (re-allocating allocated block)" );
|
2001-10-22 10:32:21 +02:00
|
|
|
}
|
|
|
|
}
|
2001-12-05 02:22:05 +01:00
|
|
|
|
2001-10-22 10:32:21 +02:00
|
|
|
/* we need to create a new node in this table */
|
2001-12-05 02:22:05 +01:00
|
|
|
node = ft_mem_table_alloc( table, sizeof ( *node ) );
|
2001-10-22 10:32:21 +02:00
|
|
|
if ( node == NULL )
|
|
|
|
ft_mem_debug_panic( "not enough memory to run memory tests" );
|
|
|
|
|
2001-12-05 02:22:05 +01:00
|
|
|
node->address = address;
|
|
|
|
node->size = size;
|
2001-10-22 16:50:41 +02:00
|
|
|
|
2001-10-24 10:04:00 +02:00
|
|
|
node->alloc_file_name = table->file_name;
|
|
|
|
node->alloc_line_no = table->line_no;
|
|
|
|
|
2001-12-05 02:22:05 +01:00
|
|
|
node->free_file_name = NULL;
|
|
|
|
node->free_line_no = 0;
|
2001-10-22 16:50:41 +02:00
|
|
|
|
2001-12-05 02:22:05 +01:00
|
|
|
node->link = pnode[0];
|
2001-10-22 10:32:21 +02:00
|
|
|
|
|
|
|
pnode[0] = node;
|
|
|
|
table->nodes++;
|
|
|
|
|
|
|
|
table->alloc_total += size;
|
|
|
|
table->alloc_current += size;
|
2001-10-22 22:15:29 +02:00
|
|
|
if ( table->alloc_current > table->alloc_max )
|
|
|
|
table->alloc_max = table->alloc_current;
|
2001-10-22 10:32:21 +02:00
|
|
|
|
2001-12-05 02:22:05 +01:00
|
|
|
if ( table->nodes * 3 < table->size ||
|
|
|
|
table->size * 3 < table->nodes )
|
2001-10-22 10:32:21 +02:00
|
|
|
ft_mem_table_resize( table );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
ft_mem_table_remove( FT_MemTable table,
|
|
|
|
FT_Byte* address )
|
|
|
|
{
|
2001-12-05 02:22:05 +01:00
|
|
|
if ( table )
|
2001-10-22 10:32:21 +02:00
|
|
|
{
|
|
|
|
FT_MemNode *pnode, node;
|
|
|
|
|
2001-12-05 02:22:05 +01:00
|
|
|
|
2001-10-22 10:32:21 +02:00
|
|
|
pnode = ft_mem_table_get_nodep( table, address );
|
|
|
|
node = *pnode;
|
2001-12-05 02:22:05 +01:00
|
|
|
if ( node )
|
2001-10-22 10:32:21 +02:00
|
|
|
{
|
|
|
|
if ( node->size < 0 )
|
2001-12-05 02:22:05 +01:00
|
|
|
ft_mem_debug_panic(
|
|
|
|
"freeing memory block at %p more than once at (%s:%ld)\n"
|
|
|
|
"block allocated at (%s:%ld) and released at (%s:%ld)",
|
|
|
|
address,
|
|
|
|
FT_FILENAME( table->file_name ), table->line_no,
|
|
|
|
FT_FILENAME( node->alloc_file_name ), node->alloc_line_no,
|
|
|
|
FT_FILENAME( node->free_file_name ), node->free_line_no );
|
|
|
|
|
2001-10-22 10:32:21 +02:00
|
|
|
/* we simply invert the node's size to indicate that the node */
|
2001-12-05 02:22:05 +01:00
|
|
|
/* was freed. We also change its contents. */
|
2001-10-26 18:58:27 +02:00
|
|
|
MEM_Set( address, 0xF3, node->size );
|
2001-10-24 10:04:00 +02:00
|
|
|
|
2001-10-22 10:32:21 +02:00
|
|
|
table->alloc_current -= node->size;
|
|
|
|
node->size = -node->size;
|
2001-10-24 10:04:00 +02:00
|
|
|
node->free_file_name = table->file_name;
|
|
|
|
node->free_line_no = table->line_no;
|
2001-10-22 10:32:21 +02:00
|
|
|
}
|
|
|
|
else
|
2001-12-05 02:22:05 +01:00
|
|
|
ft_mem_debug_panic(
|
|
|
|
"trying to free unknown block at %p in (%s:%ld)\n",
|
|
|
|
address,
|
|
|
|
FT_FILENAME( table->file_name ), table->line_no );
|
2001-10-22 10:32:21 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
extern FT_Pointer
|
|
|
|
ft_mem_debug_alloc( FT_Memory memory,
|
|
|
|
FT_Long size )
|
|
|
|
{
|
|
|
|
FT_MemTable table = memory->user;
|
|
|
|
FT_Byte* block;
|
|
|
|
|
2001-12-05 02:22:05 +01:00
|
|
|
|
2001-10-22 10:32:21 +02:00
|
|
|
if ( size <= 0 )
|
|
|
|
ft_mem_debug_panic( "negative block size allocation (%ld)", size );
|
2001-12-05 02:22:05 +01:00
|
|
|
|
2001-10-24 09:32:55 +02:00
|
|
|
block = ft_mem_table_alloc( table, size );
|
2001-10-22 10:32:21 +02:00
|
|
|
if ( block )
|
|
|
|
ft_mem_table_set( table, block, (FT_ULong)size );
|
2001-10-24 10:04:00 +02:00
|
|
|
|
|
|
|
table->file_name = NULL;
|
|
|
|
table->line_no = 0;
|
2001-12-05 02:22:05 +01:00
|
|
|
|
2001-10-22 10:32:21 +02:00
|
|
|
return (FT_Pointer) block;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
extern void
|
|
|
|
ft_mem_debug_free( FT_Memory memory,
|
|
|
|
FT_Pointer block )
|
|
|
|
{
|
|
|
|
FT_MemTable table = memory->user;
|
2001-12-05 02:22:05 +01:00
|
|
|
|
|
|
|
|
2001-10-22 10:32:21 +02:00
|
|
|
if ( block == NULL )
|
2001-10-24 10:04:00 +02:00
|
|
|
ft_mem_debug_panic( "trying to free NULL in (%s:%ld)",
|
|
|
|
FT_FILENAME( table->file_name ),
|
|
|
|
table->line_no );
|
2001-12-05 02:22:05 +01:00
|
|
|
|
2001-10-22 10:32:21 +02:00
|
|
|
ft_mem_table_remove( table, (FT_Byte*)block );
|
2001-12-05 02:22:05 +01:00
|
|
|
|
2001-10-22 10:32:21 +02:00
|
|
|
/* we never really free the block */
|
2001-10-24 10:04:00 +02:00
|
|
|
table->file_name = NULL;
|
|
|
|
table->line_no = 0;
|
2001-10-22 10:32:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
extern FT_Pointer
|
|
|
|
ft_mem_debug_realloc( FT_Memory memory,
|
|
|
|
FT_Long cur_size,
|
|
|
|
FT_Long new_size,
|
|
|
|
FT_Pointer block )
|
|
|
|
{
|
|
|
|
FT_MemTable table = memory->user;
|
|
|
|
FT_MemNode node, *pnode;
|
|
|
|
FT_Pointer new_block;
|
|
|
|
|
2001-12-05 02:22:05 +01:00
|
|
|
const char* file_name = FT_FILENAME( table->file_name );
|
2001-10-24 10:04:00 +02:00
|
|
|
FT_Long line_no = table->line_no;
|
|
|
|
|
2001-12-05 02:22:05 +01:00
|
|
|
|
2001-10-22 10:32:21 +02:00
|
|
|
if ( block == NULL || cur_size == 0 )
|
2001-10-24 10:04:00 +02:00
|
|
|
ft_mem_debug_panic( "trying to reallocate NULL in (%s:%ld)",
|
|
|
|
file_name, line_no );
|
2001-12-05 02:22:05 +01:00
|
|
|
|
2001-10-22 10:32:21 +02:00
|
|
|
if ( new_size <= 0 )
|
2001-12-05 02:22:05 +01:00
|
|
|
ft_mem_debug_panic(
|
|
|
|
"trying to reallocate %p to size 0 (current is %ld) in (%s:%ld)",
|
|
|
|
block, cur_size, file_name, line_no );
|
|
|
|
|
|
|
|
/* check 'cur_size' value */
|
2001-10-22 10:32:21 +02:00
|
|
|
pnode = ft_mem_table_get_nodep( table, (FT_Byte*)block );
|
|
|
|
node = *pnode;
|
2001-12-05 02:22:05 +01:00
|
|
|
if ( !node )
|
|
|
|
ft_mem_debug_panic(
|
|
|
|
"trying to reallocate unknown block at %p in (%s:%ld)",
|
|
|
|
block, file_name, line_no );
|
|
|
|
|
2001-10-22 10:32:21 +02:00
|
|
|
if ( node->size <= 0 )
|
2001-12-05 02:22:05 +01:00
|
|
|
ft_mem_debug_panic(
|
|
|
|
"trying to reallocate freed block at %p in (%s:%ld)",
|
|
|
|
block, file_name, line_no );
|
|
|
|
|
2001-10-22 10:32:21 +02:00
|
|
|
if ( node->size != cur_size )
|
|
|
|
ft_mem_debug_panic( "invalid realloc request for %p. cur_size is "
|
2001-10-24 10:04:00 +02:00
|
|
|
"%ld instead of %ld in (%s:%ld)",
|
|
|
|
block, cur_size, node->size, file_name, line_no );
|
2001-12-05 02:22:05 +01:00
|
|
|
|
2001-10-22 10:32:21 +02:00
|
|
|
new_block = ft_mem_debug_alloc( memory, new_size );
|
|
|
|
if ( new_block == NULL )
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
memcpy( new_block, block, cur_size < new_size ? cur_size : new_size );
|
|
|
|
|
2001-10-24 10:04:00 +02:00
|
|
|
table->file_name = file_name;
|
|
|
|
table->line_no = line_no;
|
|
|
|
|
2001-10-22 10:32:21 +02:00
|
|
|
ft_mem_debug_free( memory, (FT_Byte*)block );
|
2001-12-05 02:22:05 +01:00
|
|
|
|
2001-10-22 10:32:21 +02:00
|
|
|
return new_block;
|
|
|
|
}
|
2001-12-05 02:22:05 +01:00
|
|
|
|
|
|
|
|
2001-10-22 10:32:21 +02:00
|
|
|
extern FT_Int
|
|
|
|
ft_mem_debug_init( FT_Memory memory )
|
|
|
|
{
|
|
|
|
FT_MemTable table;
|
|
|
|
FT_Int result = 0;
|
2001-10-22 22:15:29 +02:00
|
|
|
|
2001-12-05 02:22:05 +01:00
|
|
|
|
|
|
|
if ( getenv( "FT_DEBUG_MEMORY" ) )
|
|
|
|
{
|
2001-10-24 09:32:55 +02:00
|
|
|
table = ft_mem_table_new( memory );
|
2001-10-22 22:15:29 +02:00
|
|
|
if ( table )
|
|
|
|
{
|
|
|
|
memory->user = table;
|
|
|
|
memory->alloc = ft_mem_debug_alloc;
|
|
|
|
memory->realloc = ft_mem_debug_realloc;
|
|
|
|
memory->free = ft_mem_debug_free;
|
|
|
|
result = 1;
|
|
|
|
}
|
2001-10-22 10:32:21 +02:00
|
|
|
}
|
|
|
|
return result;
|
2001-12-05 02:22:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-10-22 10:32:21 +02:00
|
|
|
extern void
|
|
|
|
ft_mem_debug_done( FT_Memory memory )
|
|
|
|
{
|
|
|
|
FT_MemTable table = memory->user;
|
2001-12-05 02:22:05 +01:00
|
|
|
|
|
|
|
|
2001-10-22 10:32:21 +02:00
|
|
|
if ( table )
|
|
|
|
{
|
2001-10-24 09:32:55 +02:00
|
|
|
memory->free = table->free;
|
|
|
|
memory->realloc = table->realloc;
|
|
|
|
memory->alloc = table->alloc;
|
2001-12-05 02:22:05 +01:00
|
|
|
|
2001-10-22 10:32:21 +02:00
|
|
|
ft_mem_table_destroy( table );
|
|
|
|
memory->user = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-10-22 16:50:41 +02:00
|
|
|
|
|
|
|
FT_BASE_DEF( FT_Error )
|
|
|
|
FT_Alloc_Debug( FT_Memory memory,
|
|
|
|
FT_Long size,
|
|
|
|
void* *P,
|
|
|
|
const char* file_name,
|
|
|
|
FT_Long line_no )
|
|
|
|
{
|
|
|
|
FT_MemTable table = memory->user;
|
2001-12-05 02:22:05 +01:00
|
|
|
|
|
|
|
|
2001-10-22 16:50:41 +02:00
|
|
|
if ( table )
|
|
|
|
{
|
|
|
|
table->file_name = file_name;
|
|
|
|
table->line_no = line_no;
|
|
|
|
}
|
|
|
|
return FT_Alloc( memory, size, P );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-10-24 10:04:00 +02:00
|
|
|
FT_BASE_DEF( FT_Error )
|
|
|
|
FT_Realloc_Debug( FT_Memory memory,
|
|
|
|
FT_Long current,
|
|
|
|
FT_Long size,
|
|
|
|
void* *P,
|
|
|
|
const char* file_name,
|
|
|
|
FT_Long line_no )
|
|
|
|
{
|
|
|
|
FT_MemTable table = memory->user;
|
2001-12-05 02:22:05 +01:00
|
|
|
|
|
|
|
|
2001-10-24 10:04:00 +02:00
|
|
|
if ( table )
|
|
|
|
{
|
|
|
|
table->file_name = file_name;
|
|
|
|
table->line_no = line_no;
|
|
|
|
}
|
|
|
|
return FT_Realloc( memory, current, size, P );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
FT_BASE_DEF( void )
|
|
|
|
FT_Free_Debug( FT_Memory memory,
|
|
|
|
FT_Pointer block,
|
|
|
|
const char* file_name,
|
|
|
|
FT_Long line_no )
|
|
|
|
{
|
|
|
|
FT_MemTable table = memory->user;
|
2001-12-05 02:22:05 +01:00
|
|
|
|
|
|
|
|
2001-10-24 10:04:00 +02:00
|
|
|
if ( table )
|
|
|
|
{
|
|
|
|
table->file_name = file_name;
|
|
|
|
table->line_no = line_no;
|
|
|
|
}
|
|
|
|
FT_Free( memory, block );
|
|
|
|
}
|
|
|
|
|
2001-10-22 16:50:41 +02:00
|
|
|
|
2001-10-22 10:32:21 +02:00
|
|
|
#else /* !FT_DEBUG_MEMORY */
|
2001-12-05 02:22:05 +01:00
|
|
|
|
|
|
|
/* ANSI C doesn't like empty source files */
|
2001-10-22 10:32:21 +02:00
|
|
|
extern const FT_Byte _debug_mem_dummy = 0;
|
|
|
|
|
|
|
|
#endif /* !FT_DEBUG_MEMORY */
|
2001-12-05 02:22:05 +01:00
|
|
|
|
|
|
|
|
|
|
|
/* END */
|