示例#1
0
static void
ft_mem_table_set( FT_MemTable  table,
                  FT_Byte*     address,
                  FT_ULong     size )
{
    FT_MemNode  *pnode, node;


    if ( table )
    {
        pnode = ft_mem_table_get_nodep( table, address );
        node  = *pnode;
        if ( node )
        {
            if ( node->size < 0 )
            {
                /* this block was already freed.  This means that our memory is */
                /* now completely corrupted!                                    */
                ft_mem_debug_panic(
                    "memory heap corrupted (allocating freed block)" );
            }
            else
            {
                /* this block was already allocated.  This means that our memory */
                /* is also corrupted!                                            */
                ft_mem_debug_panic(
                    "memory heap corrupted (re-allocating allocated block)" );
            }
        }

        /* we need to create a new node in this table */
        node = (FT_MemNode)ft_mem_table_alloc( table, sizeof ( *node ) );
        if ( node == NULL )
            ft_mem_debug_panic( "not enough memory to run memory tests" );

        node->address = address;
        node->size    = size;

        node->alloc_file_name = table->file_name;
        node->alloc_line_no   = table->line_no;

        node->free_file_name = NULL;
        node->free_line_no   = 0;

        node->link = pnode[0];

        pnode[0] = node;
        table->nodes++;

        table->alloc_total   += size;
        table->alloc_current += size;
        if ( table->alloc_current > table->alloc_max )
            table->alloc_max = table->alloc_current;

        if ( table->nodes * 3 < table->size  ||
                table->size  * 3 < table->nodes )
            ft_mem_table_resize( table );
    }
}
示例#2
0
  extern FT_Pointer
  ft_mem_debug_realloc( FT_Memory   memory,
                        FT_Long     cur_size,
                        FT_Long     new_size,
                        FT_Pointer  block )
  {
    FT_MemTable  table = (FT_MemTable)memory->user;
    FT_MemNode   node, *pnode;
    FT_Pointer   new_block;

    const char*  file_name = FT_FILENAME( table->file_name );
    FT_Long      line_no   = table->line_no;


    /* the following is valid according to ANSI C */
#if 0
    if ( block == NULL || cur_size == 0 )
      ft_mem_debug_panic( "trying to reallocate NULL in (%s:%ld)",
                          file_name, line_no );
#endif

    /* while the following is allowed in ANSI C also, we abort since */
    /* such case should be handled by FreeType.                      */
    if ( new_size <= 0 )
      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 */
    pnode = ft_mem_table_get_nodep( table, (FT_Byte*)block );
    node  = *pnode;
    if ( !node )
      ft_mem_debug_panic(
        "trying to reallocate unknown block at %p in (%s:%ld)",
        block, file_name, line_no );

    if ( node->size <= 0 )
      ft_mem_debug_panic(
        "trying to reallocate freed block at %p in (%s:%ld)",
        block, file_name, line_no );

    if ( node->size != cur_size )
      ft_mem_debug_panic( "invalid ft_realloc request for %p. cur_size is "
                          "%ld instead of %ld in (%s:%ld)",
                          block, cur_size, node->size, file_name, line_no );

    new_block = ft_mem_debug_alloc( memory, new_size );
    if ( new_block == NULL )
      return NULL;

    ft_memcpy( new_block, block, cur_size < new_size ? cur_size : new_size );

    table->file_name = file_name;
    table->line_no   = line_no;

    ft_mem_debug_free( memory, (FT_Byte*)block );

    return new_block;
  }
示例#3
0
extern FT_Pointer
ft_mem_debug_realloc( FT_Memory   memory,
                      FT_Long     cur_size,
                      FT_Long     new_size,
                      FT_Pointer  block )
{
    FT_MemTable  table = (FT_MemTable)memory->user;
    FT_MemNode   node, *pnode;
    FT_Pointer   new_block;

    const char*  file_name = FT_FILENAME( table->file_name );
    FT_Long      line_no   = table->line_no;


    if ( block == NULL || cur_size == 0 )
        ft_mem_debug_panic( "trying to reallocate NULL in (%s:%ld)",
                            file_name, line_no );

    if ( new_size <= 0 )
        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 */
    pnode = ft_mem_table_get_nodep( table, (FT_Byte*)block );
    node  = *pnode;
    if ( !node )
        ft_mem_debug_panic(
            "trying to reallocate unknown block at %p in (%s:%ld)",
            block, file_name, line_no );

    if ( node->size <= 0 )
        ft_mem_debug_panic(
            "trying to reallocate freed block at %p in (%s:%ld)",
            block, file_name, line_no );

    if ( node->size != cur_size )
        ft_mem_debug_panic( "invalid ft_realloc request for %p. cur_size is "
                            "%ld instead of %ld in (%s:%ld)",
                            block, cur_size, node->size, file_name, line_no );

    new_block = ft_mem_debug_alloc( memory, new_size );
    if ( new_block == NULL )
        return NULL;

    ft_memcpy( new_block, block, cur_size < new_size ? cur_size : new_size );

    table->file_name = file_name;
    table->line_no   = line_no;

    ft_mem_debug_free( memory, (FT_Byte*)block );

    return new_block;
}
示例#4
0
extern FT_Pointer
ft_mem_debug_alloc( FT_Memory  memory,
                    FT_Long    size )
{
    FT_MemTable  table = (FT_MemTable)memory->user;
    FT_Byte*     block;


    if ( size <= 0 )
        ft_mem_debug_panic( "negative block size allocation (%ld)", size );

    /* return NULL if the maximum number of allocations was reached */
    if ( table->bound_count &&
            table->alloc_count >= table->alloc_count_max )
        return NULL;

    /* return NULL if this allocation would overflow the maximum heap size */
    if ( table->bound_total &&
            table->alloc_current + (FT_ULong)size > table->alloc_total_max )
        return NULL;

    block = (FT_Byte *)ft_mem_table_alloc( table, size );
    if ( block )
        ft_mem_table_set( table, block, (FT_ULong)size );

    table->alloc_count++;

    table->file_name = NULL;
    table->line_no   = 0;

    return (FT_Pointer) block;
}
示例#5
0
文件: ftdbgmem.c 项目: 93i/godot
  static FT_Pointer
  ft_mem_debug_alloc( FT_Memory  memory,
                      FT_Long    size )
  {
    FT_MemTable  table = (FT_MemTable)memory->user;
    FT_Byte*     block;


    if ( size <= 0 )
      ft_mem_debug_panic( "negative block size allocation (%ld)", size );

    /* return NULL if the maximum number of allocations was reached */
    if ( table->bound_count                           &&
         table->alloc_count >= table->alloc_count_max )
      return NULL;

    /* return NULL if this allocation would overflow the maximum heap size */
    if ( table->bound_total                                   &&
         table->alloc_total_max - table->alloc_current > size )
      return NULL;

    block = (FT_Byte *)ft_mem_table_alloc( table, size );
    if ( block )
    {
      ft_mem_table_set( table, block, size, 0 );

      table->alloc_count++;
    }

    _ft_debug_file   = "<unknown>";
    _ft_debug_lineno = 0;

    return (FT_Pointer)block;
  }
示例#6
0
  static FT_MemSource
  ft_mem_table_get_source( FT_MemTable  table )
  {
    FT_UInt32     hash;
    FT_MemSource  node, *pnode;


    /* cast to FT_PtrDist first since void* can be larger */
    /* than FT_UInt32 and GCC 4.1.1 emits a warning       */
    hash  = (FT_UInt32)(FT_PtrDist)(void*)_ft_debug_file +
              (FT_UInt32)( 5 * _ft_debug_lineno );
    pnode = &table->sources[hash % FT_MEM_SOURCE_BUCKETS];

    for ( ;; )
    {
      node = *pnode;
      if ( node == NULL )
        break;

      if ( node->file_name == _ft_debug_file &&
           node->line_no   == _ft_debug_lineno   )
        goto Exit;

      pnode = &node->link;
    }

    node = (FT_MemSource)ft_mem_table_alloc( table, sizeof ( *node ) );
    if ( node == NULL )
      ft_mem_debug_panic(
        "not enough memory to perform memory debugging\n" );

    node->file_name = _ft_debug_file;
    node->line_no   = _ft_debug_lineno;

    node->cur_blocks = 0;
    node->max_blocks = 0;
    node->all_blocks = 0;

    node->cur_size   = 0;
    node->max_size   = 0;
    node->all_size   = 0;

    node->cur_max    = 0;

    node->link = NULL;
    node->hash = hash;
    *pnode     = node;

  Exit:
    return node;
  }
示例#7
0
static void
ft_mem_table_remove( FT_MemTable  table,
                     FT_Byte*     address )
{
    if ( table )
    {
        FT_MemNode  *pnode, node;


        pnode = ft_mem_table_get_nodep( table, address );
        node  = *pnode;
        if ( node )
        {
            if ( node->size < 0 )
                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 );

            /* we simply invert the node's size to indicate that the node */
            /* was freed.  We also change its contents.                   */
            FT_MEM_SET( address, 0xF3, node->size );

            table->alloc_current -= node->size;
            node->size            = -node->size;
            node->free_file_name  = table->file_name;
            node->free_line_no    = table->line_no;
        }
        else
            ft_mem_debug_panic(
                "trying to free unknown block at %p in (%s:%ld)\n",
                address,
                FT_FILENAME( table->file_name ), table->line_no );
    }
}
示例#8
0
  static FT_MemSource
  ft_mem_table_get_source( FT_MemTable  table )
  {
    FT_UInt32     hash;
    FT_MemSource  node, *pnode;


    hash  = (FT_UInt32)(void*)table->file_name +
              (FT_UInt32)( 5 * table->line_no );
    pnode = &table->sources[hash % FT_MEM_SOURCE_BUCKETS];

    for ( ;; )
    {
      node = *pnode;
      if ( node == NULL )
        break;

      if ( node->file_name == table->file_name &&
           node->line_no   == table->line_no   )
        goto Exit;

      pnode = &node->link;
    }

    node = (FT_MemSource)ft_mem_table_alloc( table, sizeof ( *node ) );
    if ( node == NULL )
      ft_mem_debug_panic(
        "not enough memory to perform memory debugging\n" );

    node->file_name = table->file_name;
    node->line_no   = table->line_no;

    node->cur_blocks = 0;
    node->max_blocks = 0;
    node->all_blocks = 0;

    node->cur_size   = 0;
    node->max_size   = 0;
    node->all_size   = 0;

    node->cur_max    = 0;

    node->link = NULL;
    node->hash = hash;
    *pnode     = node;

  Exit:
    return node;
  }
示例#9
0
extern void
ft_mem_debug_free( FT_Memory   memory,
                   FT_Pointer  block )
{
    FT_MemTable  table = (FT_MemTable)memory->user;


    if ( block == NULL )
        ft_mem_debug_panic( "trying to free NULL in (%s:%ld)",
                            FT_FILENAME( table->file_name ),
                            table->line_no );

    ft_mem_table_remove( table, (FT_Byte*)block );

    /* we never really free the block */
    table->file_name = NULL;
    table->line_no   = 0;
}
示例#10
0
  extern FT_Pointer
  ft_mem_debug_alloc( FT_Memory  memory,
                      FT_Long    size )
  {
    FT_MemTable  table = (FT_MemTable)memory->user;
    FT_Byte*     block;


    if ( size <= 0 )
      ft_mem_debug_panic( "negative block size allocation (%ld)", size );

    block = (FT_Byte *)ft_mem_table_alloc( table, size );
    if ( block )
      ft_mem_table_set( table, block, (FT_ULong)size );

    table->file_name = NULL;
    table->line_no   = 0;

    return (FT_Pointer) block;
  }
示例#11
0
  extern void
  ft_mem_debug_free( FT_Memory   memory,
                     FT_Pointer  block )
  {
    FT_MemTable  table = (FT_MemTable)memory->user;


    if ( block == NULL )
      ft_mem_debug_panic( "trying to free NULL in (%s:%ld)",
                          FT_FILENAME( _ft_debug_file ),
                          _ft_debug_lineno );

    ft_mem_table_remove( table, (FT_Byte*)block, 0 );

    if ( !table->keep_alive )
      ft_mem_table_free( table, block );

    table->alloc_count--;

    _ft_debug_file   = "<unknown>";
    _ft_debug_lineno = 0;
  }
示例#12
0
static void
ft_mem_table_destroy( FT_MemTable  table )
{
    FT_ULong  i;


    if ( table )
    {
        FT_Long    leak_count = 0;
        FT_ULong   leaks = 0;


        for ( i = 0; i < table->size; i++ )
        {
            FT_MemNode  *pnode = table->buckets + i, next, node = *pnode;


            while ( node )
            {
                next       = node->link;
                node->link = 0;

                if ( node->size > 0 )
                {
                    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 );

                    leak_count++;
                    leaks += node->size;

                    ft_mem_table_free( table, node->address );
                }

                node->address = NULL;
                node->size    = 0;

                free( node );
                node = next;
            }
            table->buckets[i] = 0;
        }
        ft_mem_table_free( table, table->buckets );
        table->buckets = NULL;

        table->size   = 0;
        table->nodes  = 0;

        printf(
            "FreeType: total memory allocations = %ld\n", table->alloc_total );
        printf(
            "FreeType: maximum memory footprint = %ld\n", table->alloc_max );

        free( table );

        if ( leak_count > 0 )
            ft_mem_debug_panic(
                "FreeType: %ld bytes of memory leaked in %ld blocks\n",
                leaks, leak_count );
        printf( "FreeType: No memory leaks detected!\n" );
    }
}
示例#13
0
  extern FT_Pointer
  ft_mem_debug_realloc( FT_Memory   memory,
                        FT_Long     cur_size,
                        FT_Long     new_size,
                        FT_Pointer  block )
  {
    FT_MemTable  table = (FT_MemTable)memory->user;
    FT_MemNode   node, *pnode;
    FT_Pointer   new_block;
    FT_Long      delta;

    const char*  file_name = FT_FILENAME( _ft_debug_file );
    FT_Long      line_no   = _ft_debug_lineno;


    /* unlikely, but possible */
    if ( new_size == cur_size )
      return block;

    /* the following is valid according to ANSI C */
#if 0
    if ( block == NULL || cur_size == 0 )
      ft_mem_debug_panic( "trying to reallocate NULL in (%s:%ld)",
                          file_name, line_no );
#endif

    /* while the following is allowed in ANSI C also, we abort since */
    /* such case should be handled by FreeType.                      */
    if ( new_size <= 0 )
      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 */
    pnode = ft_mem_table_get_nodep( table, (FT_Byte*)block );
    node  = *pnode;
    if ( !node )
      ft_mem_debug_panic(
        "trying to reallocate unknown block at %p in (%s:%ld)",
        block, file_name, line_no );

    if ( node->size <= 0 )
      ft_mem_debug_panic(
        "trying to reallocate freed block at %p in (%s:%ld)",
        block, file_name, line_no );

    if ( node->size != cur_size )
      ft_mem_debug_panic( "invalid ft_realloc request for %p. cur_size is "
                          "%ld instead of %ld in (%s:%ld)",
                          block, cur_size, node->size, file_name, line_no );

    /* return NULL if the maximum number of allocations was reached */
    if ( table->bound_count                           &&
         table->alloc_count >= table->alloc_count_max )
      return NULL;

    delta = (FT_Long)( new_size - cur_size );

    /* return NULL if this allocation would overflow the maximum heap size */
    if ( delta > 0                                                       &&
         table->bound_total                                              &&
         table->alloc_current + (FT_ULong)delta > table->alloc_total_max )
      return NULL;

    new_block = (FT_Byte *)ft_mem_table_alloc( table, new_size );
    if ( new_block == NULL )
      return NULL;

    ft_mem_table_set( table, (FT_Byte*)new_block, new_size, delta );

    ft_memcpy( new_block, block, cur_size < new_size ? cur_size : new_size );

    ft_mem_table_remove( table, (FT_Byte*)block, delta );

    _ft_debug_file   = "<unknown>";
    _ft_debug_lineno = 0;

    if ( !table->keep_alive )
      ft_mem_table_free( table, block );

    return new_block;
  }
示例#14
0
  static void
  ft_mem_table_remove( FT_MemTable  table,
                       FT_Byte*     address,
                       FT_Long      delta )
  {
    if ( table )
    {
      FT_MemNode  *pnode, node;


      pnode = ft_mem_table_get_nodep( table, address );
      node  = *pnode;
      if ( node )
      {
        FT_MemSource  source;


        if ( node->size < 0 )
          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( _ft_debug_file ), _ft_debug_lineno,
            FT_FILENAME( node->source->file_name ), node->source->line_no,
            FT_FILENAME( node->free_file_name ), node->free_line_no );

        /* scramble the node's content for additional safety */
        FT_MEM_SET( address, 0xF3, node->size );

        if ( delta == 0 )
        {
          source = node->source;

          source->cur_blocks--;
          source->cur_size -= node->size;

          table->alloc_current -= node->size;
        }

        if ( table->keep_alive )
        {
          /* we simply invert the node's size to indicate that the node */
          /* was freed.                                                 */
          node->size           = -node->size;
          node->free_file_name = _ft_debug_file;
          node->free_line_no   = _ft_debug_lineno;
        }
        else
        {
          table->nodes--;

          *pnode = node->link;

          node->size   = 0;
          node->source = NULL;

          ft_mem_table_free( table, node );

          if ( table->nodes * 3 < table->size  ||
               table->size  * 3 < table->nodes )
            ft_mem_table_resize( table );
        }
      }
      else
        ft_mem_debug_panic(
          "trying to free unknown block at %p in (%s:%ld)\n",
          address,
          FT_FILENAME( _ft_debug_file ), _ft_debug_lineno );
    }
  }
示例#15
0
  static void
  ft_mem_table_set( FT_MemTable  table,
                    FT_Byte*     address,
                    FT_ULong     size,
                    FT_Long      delta )
  {
    FT_MemNode  *pnode, node;


    if ( table )
    {
      FT_MemSource  source;


      pnode = ft_mem_table_get_nodep( table, address );
      node  = *pnode;
      if ( node )
      {
        if ( node->size < 0 )
        {
          /* This block was already freed.  Our memory is now completely */
          /* corrupted!                                                  */
          /* This can only happen in keep-alive mode.                    */
          ft_mem_debug_panic(
            "memory heap corrupted (allocating freed block)" );
        }
        else
        {
          /* This block was already allocated.  This means that our memory */
          /* is also corrupted!                                            */
          ft_mem_debug_panic(
            "memory heap corrupted (re-allocating allocated block at"
            " %p, of size %ld)\n"
            "org=%s:%d new=%s:%d\n",
            node->address, node->size,
            FT_FILENAME( node->source->file_name ), node->source->line_no,
            FT_FILENAME( _ft_debug_file ), _ft_debug_lineno );
        }
      }

      /* we need to create a new node in this table */
      node = (FT_MemNode)ft_mem_table_alloc( table, sizeof ( *node ) );
      if ( node == NULL )
        ft_mem_debug_panic( "not enough memory to run memory tests" );

      node->address = address;
      node->size    = size;
      node->source  = source = ft_mem_table_get_source( table );

      if ( delta == 0 )
      {
        /* this is an allocation */
        source->all_blocks++;
        source->cur_blocks++;
        if ( source->cur_blocks > source->max_blocks )
          source->max_blocks = source->cur_blocks;
      }

      if ( size > (FT_ULong)source->cur_max )
        source->cur_max = size;

      if ( delta != 0 )
      {
        /* we are growing or shrinking a reallocated block */
        source->cur_size     += delta;
        table->alloc_current += delta;
      }
      else
      {
        /* we are allocating a new block */
        source->cur_size     += size;
        table->alloc_current += size;
      }

      source->all_size += size;

      if ( source->cur_size > source->max_size )
        source->max_size = source->cur_size;

      node->free_file_name = NULL;
      node->free_line_no   = 0;

      node->link = pnode[0];

      pnode[0] = node;
      table->nodes++;

      table->alloc_total += size;

      if ( table->alloc_current > table->alloc_max )
        table->alloc_max = table->alloc_current;

      if ( table->nodes * 3 < table->size  ||
           table->size  * 3 < table->nodes )
        ft_mem_table_resize( table );
    }
  }
示例#16
0
  static void
  ft_mem_table_destroy( FT_MemTable  table )
  {
    FT_ULong  i;


    FT_DumpMemory( table->memory );

    if ( table )
    {
      FT_Long   leak_count = 0;
      FT_ULong  leaks      = 0;


      /* remove all blocks from the table, revealing leaked ones */
      for ( i = 0; i < table->size; i++ )
      {
        FT_MemNode  *pnode = table->buckets + i, next, node = *pnode;


        while ( node )
        {
          next       = node->link;
          node->link = 0;

          if ( node->size > 0 )
          {
            FT_PRINTF(
              "leaked memory block at address %p, size %8ld in (%s:%ld)\n",
              node->address, node->size,
              FT_FILENAME( node->source->file_name ),
              node->source->line_no );

            leak_count++;
            leaks += node->size;

            ft_mem_table_free( table, node->address );
          }

          node->address = NULL;
          node->size    = 0;

          ft_mem_table_free( table, node );
          node = next;
        }
        table->buckets[i] = 0;
      }

      ft_mem_table_free( table, table->buckets );
      table->buckets = NULL;

      table->size  = 0;
      table->nodes = 0;

      /* remove all sources */
      for ( i = 0; i < FT_MEM_SOURCE_BUCKETS; i++ )
      {
        FT_MemSource  source, next;


        for ( source = table->sources[i]; source != NULL; source = next )
        {
          next = source->link;
          ft_mem_table_free( table, source );
        }

        table->sources[i] = NULL;
      }

      FT_PRINTF(
        "FreeType: total memory allocations = %ld\n", table->alloc_total );
      FT_PRINTF(
        "FreeType: maximum memory footprint = %ld\n", table->alloc_max );

      ft_mem_table_free( table, table );

      if ( leak_count > 0 )
        ft_mem_debug_panic(
          "FreeType: %ld bytes of memory leaked in %ld blocks\n",
          leaks, leak_count );

      FT_PRINTF( "FreeType: No memory leaks detected!\n" );
    }
  }