⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hugemem.c

📁 字体缩放显示
💻 C
字号:
/******************************************************************* * *  hugemem.c * *    Memory management component (body) *    for dealing with "huge" objects with 16-bit Windows. * *  Written by Antoine Leca based on ideas from Dave Hoo. *  Copyright 1999-2000 Dave Hoo, Antoine Leca, *  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. * ******************************************************************/#include <limits.h>#include <windows.h>#include "ttdebug.h"#include "ttmemory.h"#include "ttengine.h"#ifndef TT_HUGE_PTR#error  "This component needs TT_HUGE_PTR to be #defined."#endif#ifdef  TT_CONFIG_OPTION_THREAD_SAFE#error  "This component needs static allocation and is not re-entrant."#endif  /* If the memory reclaimed is abobve this limit, alloc directly from */  /* global heap. Else, alloc using malloc (using suballocation).      */#ifndef MEMORY_MIN_GLOBAL#define MEMORY_MIN_GLOBAL   4096#endif/* required by the tracing mode */#undef  TT_COMPONENT#define TT_COMPONENT  trace_memory#ifdef DEBUG_MEMORY#include <stdio.h>#define MAX_TRACKED_BLOCKS  1024  struct  TMemRec_  {    void*  base;    Long   size;  };  typedef struct TMemRec_  TMemRec;  static TMemRec  pointers[MAX_TRACKED_BLOCKS + 1];  static Int  num_alloc;  static Int  num_free;  static Int  num_realloc; /* counts only `real' reallocations                              (i.e., an existing buffer will be resized                              to a value larger than zero */  static Int  fail_alloc;  static Int  fail_realloc;  static Int  fail_free;#else  /* We need a tracing stack of the calls to big chunks of memory,   */  /* in order to call the matching version of free().                */#define MAX_TRACKED_BIGCHUNKS    64  struct  TMemRec_  {    void*  base;  };  typedef struct TMemRec_  TMemRec;  static TMemRec  pointers[MAX_TRACKED_BIGCHUNKS + 1];#endif /* DEBUG_MEMORY */#ifndef TT_CONFIG_REENTRANT  Long  TTMemory_Allocated;  Long  TTMemory_MaxAllocated;#endif/******************************************************************* * *  Function    :  TT_Alloc * *  Description :  Allocates memory from the heap buffer. * *  Input  :  Size      size of the memory to be allocated *            P         pointer to a buffer pointer * *  Output :  Error code. * *  NOTE :  The newly allocated block should _always_ be zeroed *          on return.  Many parts of the engine rely on this to *          work properly. * ******************************************************************/  FT_EXPORT_FUNC( TT_Error )  TT_Alloc( ULong  Size, void**  P )  {    Int  i;    if ( !P )      return TT_Err_Invalid_Argument;        /* Also see below for another case of "invalid argument". */    if ( Size > 0 )    {      if ( Size >= MEMORY_MIN_GLOBAL )      {        HANDLE  hMem;        hMem = GlobalAlloc( GMEM_ZEROINIT, Size );        if ( !hMem )          return TT_Err_Out_Of_Memory;        *P = (void*)GlobalLock( hMem );      }      else        *P = (void*)malloc( Size );      if ( !*P )        return TT_Err_Out_Of_Memory;#ifndef TT_CONFIG_REENTRANT      TTMemory_MaxAllocated += Size;      TTMemory_Allocated    += Size;#endif#ifdef DEBUG_MEMORY      num_alloc++;      i = 0;      while ( i < MAX_TRACKED_BLOCKS && pointers[i].base != NULL )        i++;      if ( i >= MAX_TRACKED_BLOCKS )        fail_alloc++;      else      {        pointers[i].base = *P;        pointers[i].size = Size;      }#else      if ( Size >= MEMORY_MIN_GLOBAL )      {        i = 0;        while ( i < MAX_TRACKED_BIGCHUNKS && pointers[i].base != NULL )          i++;        if ( i >= MAX_TRACKED_BIGCHUNKS )          /* We fail badly here. Increase MAX_TRACKED_BIGCHUNKS if needed. */          return TT_Err_Invalid_Argument;        else          pointers[i].base = *P;      }#endif /* DEBUG_MEMORY */      /* The nice thing about GlobalAlloc is that it zeroes the memory. */      if ( Size < MEMORY_MIN_GLOBAL )        MEM_Set( *P, 0, Size );    }    else      *P = NULL;    return TT_Err_Ok;  }#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE/******************************************************************* * *  Function    :  TT_Realloc * *  Description :  Reallocates memory from the heap buffer. * *  Input  :  Size      new size of the memory to be allocated; *                      if zero, TT_Free() will be called *            P         pointer to a buffer pointer; if *P == NULL, *                      TT_Alloc() will be called * *  Output :  Error code. * *  NOTES :  It's not necessary to zero the memory in case the  *           reallocated buffer is larger than before -- the *           application has to take care of this. * *           If the memory request fails, TT_Free() will be *           called on *P, and TT_Err_Out_Of_Memory returned. * ******************************************************************/  FT_EXPORT_FUNC( TT_Error )  TT_Realloc( ULong  Size, void**  P )  {    ULong   oldSize;    void*   Q;    Int  i;    if ( !P )      return TT_Err_Invalid_Argument;    if ( !*P )      return TT_Alloc( Size, P );    if ( Size == 0 )      return TT_Free( P );#ifdef DEBUG_MEMORY    num_realloc++;    i = 0;    while ( i < MAX_TRACKED_BLOCKS && pointers[i].base != *P )      i++;    if ( i >= MAX_TRACKED_BLOCKS )      fail_realloc++;    else      oldSize = pointers[i].size;#else    i = 0;    while ( i < MAX_TRACKED_BIGCHUNKS && pointers[i].base != *P )      i++;    /* If we did not found the pointer, then this is a "small" chunk. */    if ( i < MAX_TRACKED_BIGCHUNKS )    {        /* Signal we found a big one. Real size does not matter. */      oldSize = MEMORY_MIN_GLOBAL;    }#endif /* DEBUG_MEMORY */    if ( oldSize >= MEMORY_MIN_GLOBAL )    {      /* Deal with a big chunk. */      HANDLE hMem, hNewMem;      hMem = GlobalHandle ( (ULong)*P >> 16 ) & 0xFFFF;      if ( !hMem )  /* Bad call... */        return TT_Err_Invalid_Argument;      GlobalUnlock( hMem );	  hNewMem = GlobalReAlloc( hMem, Size, 0 );      if ( hNewMem )        *P = (void*)GlobalLock( hNewMem );    }    if ( Size >= MEMORY_MIN_GLOBAL )    {      /* A small chunk crosses the limit... */      if( TT_Alloc( Size, &Q ) != TT_Err_Ok )        Q = NULL;  /* Failed to create the new block. */      else        MEM_Copy( Q, *P, oldSize );          /* We need to register the new entry. */#ifndef DEBUG_MEMORY      i = 0;      while ( i < MAX_TRACKED_BIGCHUNKS && pointers[i].base != NULL )        i++;      if ( i >= MAX_TRACKED_BIGCHUNKS )        /* We fail badly here. Increase MAX_TRACKED_BIGCHUNKS if needed. */        return TT_Err_Invalid_Argument;#endif /* DEBUG_MEMORY */    }    else      Q = (void*)realloc( *P, Size );    if ( !Q )    {      TT_Free( *P );      return TT_Err_Out_Of_Memory;    }#ifdef DEBUG_MEMORY    if ( i < MAX_TRACKED_BLOCKS )    {#ifndef TT_CONFIG_REENTRANT      TTMemory_Allocated += Size - pointers[i].size;      if ( Size > pointers[i].size )        TTMemory_MaxAllocated += Size - pointers[i].size;#endif      pointers[i].base = Q;      pointers[i].size = Size;    }#else    if ( i < MAX_TRACKED_BIGCHUNKS )    {      pointers[i].base = Q;    }#endif /* DEBUG_MEMORY */    *P = Q;    return TT_Err_Ok;  }#endif /* TT_CONFIG_OPTION_EXTEND_ENGINE *//******************************************************************* * *  Function    :  TT_Free * *  Description :  Releases a previously allocated block of memory. * *  Input  :  P    pointer to memory block * *  Output :  Always SUCCESS. * *  Note : The pointer must _always_ be set to NULL by this function. * ******************************************************************/  FT_EXPORT_FUNC( TT_Error )  TT_Free( void**  P )  {    Int  i;    Long Size = 0;    if ( !P || !*P )      return TT_Err_Ok;#ifdef DEBUG_MEMORY    num_free++;    i = 0;    while ( i < MAX_TRACKED_BLOCKS && pointers[i].base != *P )      i++;    if ( i >= MAX_TRACKED_BLOCKS )      fail_free++;    else    {#ifndef TT_CONFIG_REENTRANT      TTMemory_Allocated -= pointers[i].size;#endif      Size = pointers[i].size;      pointers[i].base = NULL;      pointers[i].size = 0;    }#else    i = 0;    while ( i < MAX_TRACKED_BIGCHUNKS && pointers[i].base != *P )      i++;    /* If we did not found the pointer, then this is a "small" chunk. */    if ( i < MAX_TRACKED_BIGCHUNKS )    {      pointers[i].base = NULL;        /* Signal we found a big one. Real size does not matter. */      Size = MEMORY_MIN_GLOBAL;    }#endif /* DEBUG_MEMORY */    if ( Size >= MEMORY_MIN_GLOBAL )    {      HANDLE hMem;      hMem = GlobalHandle ( (ULong)*P >> 16 ) & 0xFFFF;      if ( !hMem )  /* Bad call... */        return TT_Err_Invalid_Argument;      GlobalUnlock( hMem );      GlobalFree  ( hMem );    }    else      free( *P );    *P = NULL;    return TT_Err_Ok;  }/******************************************************************* * *  Function    :  TTMemory_Init * *  Description :  Initializes the memory. * *  Output :  Always SUCCESS. * ******************************************************************/  FT_INTERNAL_FUNC( TT_Error )  TTMemory_Init( void )  {#ifdef DEBUG_MEMORY    Int  i;    for ( i = 0; i < MAX_TRACKED_BLOCKS; i++ )    {      pointers[i].base = NULL;      pointers[i].size = 0;    }    num_alloc   = 0;    num_realloc = 0;    num_free    = 0;    fail_alloc   = 0;    fail_realloc = 0;    fail_free    = 0;#else    Int  i;    for ( i = 0; i < MAX_TRACKED_BIGCHUNKS; i++ )    {      pointers[i].base = NULL;    }#endif#ifndef TT_CONFIG_REENTRANT    TTMemory_Allocated    = 0;    TTMemory_MaxAllocated = 0;#endif    return TT_Err_Ok;  }/******************************************************************* * *  Function    :  TTMemory_Done * *  Description :  Finalizes memory usage. * *  Output :  Always SUCCESS. * ******************************************************************/  FT_INTERNAL_FUNC( TT_Error )  TTMemory_Done( void )  {#ifdef DEBUG_MEMORY    Int  i, num_leaked, tot_leaked;    num_leaked = 0;    tot_leaked = 0;    for ( i = 0; i < MAX_TRACKED_BLOCKS; i++ )    {      if ( pointers[i].base )      {        num_leaked ++;        tot_leaked += pointers[i].size;      }    }    fprintf( stderr,             "%d memory allocations, of which %d failed\n",             num_alloc,             fail_alloc );    fprintf( stderr,             "%d memory reallocations, of which %d failed\n",             num_realloc,             fail_realloc );    fprintf( stderr,             "%d memory frees, of which %d failed\n",             num_free,             fail_free );    if ( num_leaked > 0 )    {      fprintf( stderr,               "There are %d leaked memory blocks, totalizing %d bytes\n",               num_leaked, tot_leaked );      for ( i = 0; i < MAX_TRACKED_BLOCKS; i++ )      {        if ( pointers[i].base )        {          fprintf( stderr,                   "index: %4d (base: $%08lx, size: %08ld)\n",                   i,                   (long)pointers[i].base,                   pointers[i].size );        }      }    }    else      fprintf( stderr, "No memory leaks !\n" );#endif /* DEBUG_MEMORY */    return TT_Err_Ok;  }/* END */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -