memalloc.c

来自「clips源代码」· C语言 代码 · 共 1,000 行 · 第 1/3 页

C
1,000
字号
   /*======================================*/   newBlock->nextBlock = NULL;   newBlock->prevBlock = blockPtr;   newBlock->nextFree = (struct chunkInfo *) (((char *) newBlock) + MemoryData(theEnv)->BlockInfoSize);   newBlock->size = (long) usableBlockSize;   blockPtr->nextBlock = newBlock;   newTopChunk = (struct chunkInfo *) (((char *) newBlock) + MemoryData(theEnv)->BlockInfoSize + MemoryData(theEnv)->ChunkInfoSize + usableBlockSize);   newTopChunk->nextFree = NULL;   newTopChunk->lastFree = NULL;   newTopChunk->size = 0;   newTopChunk->prevChunk = newBlock->nextFree;   newBlock->nextFree->nextFree = NULL;   newBlock->nextFree->lastFree = NULL;   newBlock->nextFree->prevChunk = NULL;   newBlock->nextFree->size = (long) usableBlockSize;   return(1);  }/*******************************************************//* RequestChunk: Allocates memory by returning a chunk *//*   of memory from a larger block of memory.          *//*******************************************************/globle void *RequestChunk(  void *theEnv,  size_t requestSize)  {   struct chunkInfo *chunkPtr;   struct blockInfo *blockPtr;   /*==================================================*/   /* Allocate initial memory pool block if it has not */   /* already been allocated.                          */   /*==================================================*/   if (MemoryData(theEnv)->BlockMemoryInitialized == FALSE)      {       if (InitializeBlockMemory(theEnv,requestSize) == 0) return(NULL);      }   /*====================================================*/   /* Make sure that the amount of memory requested will */   /* fall on a boundary of strictest alignment          */   /*====================================================*/   requestSize = (((requestSize - 1) / STRICT_ALIGN_SIZE) + 1) * STRICT_ALIGN_SIZE;   /*=====================================================*/   /* Search through the list of free memory for a block  */   /* of the appropriate size.  If a block is found, then */   /* allocate and return a pointer to it.                */   /*=====================================================*/   blockPtr = MemoryData(theEnv)->TopMemoryBlock;   while (blockPtr != NULL)     {      chunkPtr = blockPtr->nextFree;      while (chunkPtr != NULL)        {         if ((chunkPtr->size == requestSize) ||             (chunkPtr->size > (requestSize + MemoryData(theEnv)->ChunkInfoSize)))           {            AllocateChunk(theEnv,blockPtr,chunkPtr,requestSize);            return((void *) (((char *) chunkPtr) + MemoryData(theEnv)->ChunkInfoSize));           }         chunkPtr = chunkPtr->nextFree;        }      if (blockPtr->nextBlock == NULL)        {         if (AllocateBlock(theEnv,blockPtr,requestSize) == 0)  /* get another block */           { return(NULL); }        }      blockPtr = blockPtr->nextBlock;     }   SystemError(theEnv,"MEMORY",2);   EnvExitRouter(theEnv,EXIT_FAILURE);   return(NULL); /* Unreachable, but prevents warning. */  }/********************************************//* AllocateChunk: Allocates a chunk from an *//*   existing chunk in a block of memory.   *//********************************************/static void AllocateChunk(  void *theEnv,  struct blockInfo *parentBlock,  struct chunkInfo *chunkPtr,  size_t requestSize)  {   struct chunkInfo *splitChunk, *nextChunk;   /*=============================================================*/   /* If the size of the memory chunk is an exact match for the   */   /* requested amount of memory, then the chunk can be allocated */   /* without splitting it.                                       */   /*=============================================================*/   if (requestSize == chunkPtr->size)     {      chunkPtr->size = - (long int) requestSize;      if (chunkPtr->lastFree == NULL)        {         if (chunkPtr->nextFree != NULL)           { parentBlock->nextFree = chunkPtr->nextFree; }         else           { parentBlock->nextFree = NULL; }        }      else        { chunkPtr->lastFree->nextFree = chunkPtr->nextFree; }      if (chunkPtr->nextFree != NULL)        { chunkPtr->nextFree->lastFree = chunkPtr->lastFree; }      chunkPtr->lastFree = NULL;      chunkPtr->nextFree = NULL;      return;     }   /*===========================================================*/   /* If the size of the memory chunk is larger than the memory */   /* request, then split the chunk into two pieces.            */   /*===========================================================*/   nextChunk = (struct chunkInfo *)              (((char *) chunkPtr) + MemoryData(theEnv)->ChunkInfoSize + chunkPtr->size);   splitChunk = (struct chunkInfo *)                  (((char *) chunkPtr) + (MemoryData(theEnv)->ChunkInfoSize + requestSize));   splitChunk->size = (long) (chunkPtr->size - (requestSize + MemoryData(theEnv)->ChunkInfoSize));   splitChunk->prevChunk = chunkPtr;   splitChunk->nextFree = chunkPtr->nextFree;   splitChunk->lastFree = chunkPtr->lastFree;   nextChunk->prevChunk = splitChunk;   if (splitChunk->lastFree == NULL)     { parentBlock->nextFree = splitChunk; }   else     { splitChunk->lastFree->nextFree = splitChunk; }   if (splitChunk->nextFree != NULL)     { splitChunk->nextFree->lastFree = splitChunk; }   chunkPtr->size = - (long int) requestSize;   chunkPtr->lastFree = NULL;   chunkPtr->nextFree = NULL;   return;  }/***********************************************************//* ReturnChunk: Frees memory allocated using RequestChunk. *//***********************************************************/globle int ReturnChunk(  void *theEnv,  void *memPtr,  size_t size)  {   struct chunkInfo *chunkPtr, *lastChunk, *nextChunk, *topChunk;   struct blockInfo *blockPtr;   /*=====================================================*/   /* Determine if the expected size of the chunk matches */   /* the size stored in the chunk's information record.  */   /*=====================================================*/   size = (((size - 1) / STRICT_ALIGN_SIZE) + 1) * STRICT_ALIGN_SIZE;   chunkPtr = (struct chunkInfo *) (((char *) memPtr) - MemoryData(theEnv)->ChunkInfoSize);   if (chunkPtr == NULL)     { return(FALSE); }   if (chunkPtr->size >= 0)     { return(FALSE); }   if (chunkPtr->size != - (long int) size)     { return(FALSE); }   chunkPtr->size = - chunkPtr->size;   /*=============================================*/   /* Determine in which block the chunk resides. */   /*=============================================*/   topChunk = chunkPtr;   while (topChunk->prevChunk != NULL)     { topChunk = topChunk->prevChunk; }   blockPtr = (struct blockInfo *) (((char *) topChunk) - MemoryData(theEnv)->BlockInfoSize);   /*===========================================*/   /* Determine the chunks physically preceding */   /* and following the returned chunk.         */   /*===========================================*/   lastChunk = chunkPtr->prevChunk;   nextChunk = (struct chunkInfo *) (((char *) memPtr) + size);   /*=========================================================*/   /* Add the chunk to the list of free chunks for the block. */   /*=========================================================*/   if (blockPtr->nextFree != NULL)     { blockPtr->nextFree->lastFree = chunkPtr; }   chunkPtr->nextFree = blockPtr->nextFree;   chunkPtr->lastFree = NULL;   blockPtr->nextFree = chunkPtr;   /*=====================================================*/   /* Combine this chunk with previous chunk if possible. */   /*=====================================================*/   if (lastChunk != NULL)     {      if (lastChunk->size > 0)        {         lastChunk->size += (MemoryData(theEnv)->ChunkInfoSize + chunkPtr->size);         if (nextChunk != NULL)           { nextChunk->prevChunk = lastChunk; }         else           { return(FALSE); }         if (lastChunk->lastFree != NULL)           { lastChunk->lastFree->nextFree = lastChunk->nextFree; }         if (lastChunk->nextFree != NULL)           { lastChunk->nextFree->lastFree = lastChunk->lastFree; }         lastChunk->nextFree = chunkPtr->nextFree;         if (chunkPtr->nextFree != NULL)           { chunkPtr->nextFree->lastFree = lastChunk; }         lastChunk->lastFree = NULL;         blockPtr->nextFree = lastChunk;         chunkPtr->lastFree = NULL;         chunkPtr->nextFree = NULL;         chunkPtr = lastChunk;        }     }   /*=====================================================*/   /* Combine this chunk with the next chunk if possible. */   /*=====================================================*/   if (nextChunk == NULL) return(FALSE);   if (chunkPtr == NULL) return(FALSE);   if (nextChunk->size > 0)     {      chunkPtr->size += (MemoryData(theEnv)->ChunkInfoSize + nextChunk->size);      topChunk = (struct chunkInfo *) (((char *) nextChunk) + nextChunk->size + MemoryData(theEnv)->ChunkInfoSize);      if (topChunk != NULL)        { topChunk->prevChunk = chunkPtr; }      else        { return(FALSE); }      if (nextChunk->lastFree != NULL)        { nextChunk->lastFree->nextFree = nextChunk->nextFree; }      if (nextChunk->nextFree != NULL)        { nextChunk->nextFree->lastFree = nextChunk->lastFree; }     }   /*===========================================*/   /* Free the buffer if we can, but don't free */   /* the first buffer if it's the only one.    */   /*===========================================*/   if ((chunkPtr->prevChunk == NULL) &&       (chunkPtr->size == blockPtr->size))     {      if (blockPtr->prevBlock != NULL)        {         blockPtr->prevBlock->nextBlock = blockPtr->nextBlock;         if (blockPtr->nextBlock != NULL)           { blockPtr->nextBlock->prevBlock = blockPtr->prevBlock; }         free((char *) blockPtr);        }      else        {         if (blockPtr->nextBlock != NULL)           {            blockPtr->nextBlock->prevBlock = NULL;            MemoryData(theEnv)->TopMemoryBlock = blockPtr->nextBlock;            free((char *) blockPtr);           }        }     }   return(TRUE);  }/***********************************************//* ReturnAllBlocks: Frees all allocated blocks *//*   back to the operating system.             *//***********************************************/globle void ReturnAllBlocks(  void *theEnv)  {   struct blockInfo *theBlock, *nextBlock;   /*======================================*/   /* Free up int based memory allocation. */   /*======================================*/   theBlock = MemoryData(theEnv)->TopMemoryBlock;   while (theBlock != NULL)     {      nextBlock = theBlock->nextBlock;      free((char *) theBlock);      theBlock = nextBlock;     }   MemoryData(theEnv)->TopMemoryBlock = NULL;  }#endif

⌨️ 快捷键说明

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