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

📄 gmalloc.c

📁 UNIX下SH的实现源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* The malloc headers and source files from the C library follow here.  *//* Declarations for `malloc' and friends.   Copyright 1990, 91, 92, 93, 95, 96 Free Software Foundation, Inc.		  Written May 1989 by Mike Haertel.This library is free software; you can redistribute it and/ormodify it under the terms of the GNU Library General Public License aspublished by the Free Software Foundation; either version 2 of theLicense, or (at your option) any later version.This library is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNULibrary General Public License for more details.You should have received a copy of the GNU Library General PublicLicense along with this library; see the file COPYING.LIB.  Ifot, write to the Free Software Foundation, Inc.,59 Temple Place, Suite 330, Boston, MA 02111 USA.   The author may be reached (Email) at the address mike@ai.mit.edu,   or (US mail) as Mike Haertel c/o Free Software Foundation.  *//* XXX NOTES:    1.	Augment the mstats struct so we can see how many blocks for fragments	and how many blocks for large requests were allocated.*//* CHANGES:    1.	Reorganized the source for my benefit.    2.	Integrated the range-checking code by default.    3.  free(0) no longer dumps core.    4.  Extended the statistics.    5.  Fixed a couple of places where the stats were not kept correctly.*/#ifdef	HAVE_CONFIG_H#include <config.h>#endif#if defined (HAVE_STRING_H)#  include <string.h>#else#  include <strings.h>#endif#if defined (HAVE_LIMITS_H)#  include <limits.h>#endif#if defined (HAVE_UNISTD_H)#  ifdef _MINIX#    include <sys/types.h>#  endif#  include <unistd.h>#endif#if defined (HAVE_STDDEF_H)#  include <stddef.h>#endif#include <errno.h>#if defined (RCHECK) && !defined (botch)#  include <stdio.h>#  define STDIO_H_INCLUDED#endif#include "stdc.h"#ifndef errnoextern int errno;#endif/* Need an autoconf test for this. */#if __STDC__#  undef  genptr_t#  define genptr_t	void *#else#  undef  genptr_t#  define genptr_t	char *#endif /* !__STDC__ */#if !defined (HAVE_MEMSET)#  define	memset(s, zero, n)	bzero ((s), (n))#endif#if !defined (HAVE_MEMCPY)#  define	memcpy(d, s, n)		bcopy ((s), (d), (n))#endif/* Cope with systems lacking `memmove'.    */#if !defined (HAVE_MEMMOVE) && !defined (memmove)static void malloc_safe_bcopy __P ((genptr_t, genptr_t, size_t));#  define memmove(to, from, size)	malloc_safe_bcopy ((from), (to), (size))#endif#ifndef	NULL#define	NULL	0#endif#ifndef min#define min(A, B) ((A) < (B) ? (A) : (B))#endif/* Return values for `mprobe': these are the kinds of inconsistencies that   `mcheck' enables detection of.  */enum mcheck_status  {    MCHECK_DISABLED = -1,	/* Consistency checking is not turned on.  */    MCHECK_OK,			/* Block is fine.  */    MCHECK_FREE,		/* Block freed twice.  */    MCHECK_HEAD,		/* Memory before the block was clobbered.  */    MCHECK_TAIL			/* Memory after the block was clobbered.  */  };/* Statistics available to the user.  */struct mstats  {    size_t bytes_total; /* Total size of the heap. */    size_t chunks_used; /* Chunks allocated by the user. */    size_t bytes_used;	/* Byte total of user-allocated chunks. */    size_t chunks_free; /* Chunks in the free list. */    size_t bytes_free;	/* Byte total of chunks in the free list. */    int nmalloc;	/* Total number of calls to malloc. */    int nfree;		/* Total number of calls to free. */    int nrealloc;	/* Total number of calls to realloc. */    int nsbrk;		/* Total number of calls to sbrk. */    size_t tsbrk;	/* Total number of bytes allocated via sbrk. */    int negsbrk;	/* Total number of calls to sbrk with a negative arg */    size_t tnegsbrk;	/* Total number of bytes returned to the kernel. */  };#ifdef RCHECK/* Arbitrary magical numbers.  */#define MAGICWORD	0xfedabeeb#define MAGICFREE	0xd8675309#define MAGICBYTE	((char) 0xd7)#define MALLOCFLOOD	((char) 0x93)#define FREEFLOOD	((char) 0x95)struct hdr  {    size_t size;		/* Exact size requested by user.  */    u_bits32_t magic;		/* Magic number to check header integrity.  */  };#endif /* RCHECK *//* Functions exported by this library. *//* Allocate SIZE bytes of memory.  */extern genptr_t malloc __P ((size_t __size));/* Re-allocate the previously allocated block   in genptr_t, making the new block SIZE bytes long.  */extern genptr_t realloc __P ((genptr_t __ptr, size_t __size));/* Allocate NMEMB elements of SIZE bytes each, all initialized to 0.  */extern genptr_t calloc __P ((size_t __nmemb, size_t __size));/* Free a block allocated by `malloc', `realloc' or `calloc'.  */extern void free __P ((genptr_t __ptr));/* Allocate SIZE bytes allocated to ALIGNMENT bytes.  */extern genptr_t memalign __P ((size_t __alignment, size_t __size));/* Pick up the current statistics. */extern struct mstats mstats __P ((void));#ifdef RCHECKextern enum mcheck_status mprobe __P((genptr_t ptr));#endif/* End of exported functions. *//* The allocator divides the heap into blocks of fixed size; large   requests receive one or more whole blocks, and small requests   receive a fragment of a block.  Fragment sizes are powers of two,   and all fragments of a block are the same size.  When all the   fragments in a block have been freed, the block itself is freed.  */#define BLOCKLOG	12#define BLOCKSIZE	4096		/* 1 << BLOCKLOG */#define BLOCKIFY(SIZE)	(((SIZE) + BLOCKSIZE - 1) / BLOCKSIZE)/* Determine the amount of memory spanned by the initial heap table   (not an absolute limit).  */#define HEAP		4194304		/* 1 << 22 *//* Number of contiguous free blocks allowed to build up at the end of   memory before they will be returned to the system.  */#define FINAL_FREE_BLOCKS	8/* Data structure giving per-block information.  */typedef union  {    /* Heap information for a busy block.  */    struct      {	/* Zero for a large (multiblock) object, or positive giving the	   logarithm to the base two of the fragment size.  */	int type;	union	  {	    struct	      {		size_t nfree; /* Free frags in a fragmented block.  */		size_t first; /* First free fragment of the block.  */	      } frag;	    /* For a large object, in its first block, this has the number	       of blocks in the object.  In the other blocks, this has a	       negative number which says how far back the first block is.  */	    ptrdiff_t size;	  } info;      } busy;    /* Heap information for a free block (that may be the first of a       free cluster).  */    struct      {	size_t size;	/* Size (in blocks) of a free cluster.  */	size_t next;	/* Index of next free cluster.  */	size_t prev;	/* Index of previous free cluster.  */      } free;  } malloc_info;/* Pointer to first block of the heap.  */static char *_heapbase;/* Table indexed by block number giving per-block information.  */static malloc_info *_heapinfo;/* Address to block number and vice versa.  */#define BLOCK(A)	(((char *) (A) - _heapbase) / BLOCKSIZE + 1)#define ADDRESS(B)	((genptr_t) (((B) - 1) * BLOCKSIZE + _heapbase))/* Number of info entries.  */static size_t heapsize;/* Current search index for the heap table.  */static size_t _heapindex;/* Limit of valid info table indices.  */static size_t _heaplimit;/* Doubly linked lists of free fragments.  */struct list  {    struct list *next;    struct list *prev;  };/* Free list headers for each fragment size.  */static struct list _fraghead[BLOCKLOG];/* List of blocks allocated with `memalign'.  */struct alignlist  {    struct alignlist *next;    genptr_t aligned;		/* The address that memaligned returned.  */    genptr_t exact;		/* The address that malloc returned.  */  };/* List of blocks allocated by memalign.  */static struct alignlist *_aligned_blocks = NULL;/* Internal versions of `malloc', `realloc', and `free'   used when these functions need to call each other. */static genptr_t imalloc __P ((size_t __size));static genptr_t irealloc __P ((genptr_t __ptr, size_t __size));static void ifree __P ((genptr_t __ptr));/* Given an address in the middle of a malloc'd object,   return the address of the beginning of the object.  */static genptr_t malloc_find_object_address __P ((genptr_t __ptr));/* Underlying allocation function; successive calls should   return contiguous pieces of memory.  */static genptr_t default_morecore __P ((ptrdiff_t __size));/* Number of extra blocks to get each time we ask for more core.   This reduces the frequency of calling `default_morecore'.  */static size_t malloc_extra_blocks;/* Nonzero if `malloc' has been called and done its initialization.  */static int malloc_initialized;/* Function called to initialize malloc data structures.  */static int malloc_initialize __P ((void));#ifdef RCHECKstatic void zmemset __P((genptr_t, int, size_t));static enum mcheck_status checkhdr __P((const struct hdr *));static void mabort __P((enum mcheck_status));#endif/* Instrumentation.  */static size_t chunks_used;static size_t bytes_used;static size_t chunks_free;static size_t bytes_free;static int nmalloc, nfree, nrealloc;static int nsbrk;static size_t tsbrk;static int negsbrk;static size_t tnegsbrk;/* Aligned allocation.  */static genptr_talign (size)     size_t size;{  genptr_t result;  unsigned long int adj;  result = default_morecore (size);  adj = (unsigned long int) ((unsigned long int) ((char *) result -						  (char *) NULL)) % BLOCKSIZE;  if (adj != 0)    {      genptr_t new;      adj = BLOCKSIZE - adj;      new = default_morecore (adj);      result = (char *) result + adj;    }  return result;}/* Get SIZE bytes, if we can get them starting at END.   Return the address of the space we got.   If we cannot get space at END, fail and return -1.  */static genptr_tget_contiguous_space (size, position)     ptrdiff_t size;     genptr_t position;{  genptr_t before;  genptr_t after;  before = default_morecore (0);  /* If we can tell in advance that the break is at the wrong place,     fail now.  */  if (before != position)    return 0;  /* Allocate SIZE bytes and get the address of them.  */  after = default_morecore (size);  if (!after)    return 0;  /* It was not contiguous--reject it.  */  if (after != position)    {      default_morecore (- size);      return 0;    }  return after;}/* This is called when `_heapinfo' and `heapsize' have just   been set to describe a new info table.  Set up the table   to describe itself and account for it in the statistics.  */inline static voidregister_heapinfo (){  size_t block, blocks;  block = BLOCK (_heapinfo);  blocks = BLOCKIFY (heapsize * sizeof (malloc_info));  /* Account for the _heapinfo block itself in the statistics.  */  bytes_used += blocks * BLOCKSIZE;  ++chunks_used;  /* Describe the heapinfo block itself in the heapinfo.  */  _heapinfo[block].busy.type = 0;  _heapinfo[block].busy.info.size = blocks;  /* Leave back-pointers for malloc_find_address.  */  while (--blocks > 0)    _heapinfo[block + blocks].busy.info.size = -blocks;}/* Set everything up and remember that we have.  */static intmalloc_initialize (){  if (malloc_initialized)    return 0;  heapsize = HEAP / BLOCKSIZE;  _heapinfo = (malloc_info *) align (heapsize * sizeof (malloc_info));  if (_heapinfo == NULL)    return 0;  memset (_heapinfo, 0, heapsize * sizeof (malloc_info));  _heapinfo[0].free.size = 0;  _heapinfo[0].free.next = _heapinfo[0].free.prev = 0;  _heapindex = 0;  _heapbase = (char *) _heapinfo;  _heaplimit = BLOCK (_heapbase + heapsize * sizeof (malloc_info));  register_heapinfo ();  malloc_initialized = 1;  return 1;}/* Allocate INCREMENT more bytes of data space,   and return the start of data space, or NULL on errors.   If INCREMENT is negative, shrink data space.  */static genptr_tdefault_morecore (increment)     ptrdiff_t increment;{  genptr_t result;  nsbrk++;  tsbrk += increment;  if (increment < 0)    {      negsbrk++;      tnegsbrk += -increment;    }  result = (genptr_t) sbrk (increment);  if ((long)result == -1L)    return NULL;  return result;}static int morecore_recursing;/* Get neatly aligned memory, initializing or   growing the heap info table as necessary. */static genptr_tmorecore (size)     size_t size;{  genptr_t result;  malloc_info *newinfo, *oldinfo;  size_t newsize;  if (morecore_recursing)    /* Avoid recursion.  The caller will know how to handle a null return.  */    return NULL;  result = align (size);  if (result == NULL)    return NULL;  /* Check if we need to grow the info table.  */  if ((size_t) BLOCK ((char *) result + size) > heapsize)    {      /* Calculate the new _heapinfo table size.  We do not account for the	 added blocks in the table itself, as we hope to place them in	 existing free space, which is already covered by part of the	 existing table.  */      newsize = heapsize;      do	newsize <<= 1;      while ((size_t) BLOCK ((char *) result + size) > newsize);      /* We must not reuse existing core for the new info table when called	 from realloc in the case of growing a large block, because the	 block being grown is momentarily marked as free.  In this case	 _heaplimit is zero so we know not to reuse space for internal	 allocation.  */      if (_heaplimit != 0)	{	  /* First try to allocate the new info table in core we already	     have, in the usual way using realloc.  If realloc cannot	     extend it in place or relocate it to existing sufficient core,	     we will get called again, and the code above will notice the	     `morecore_recursing' flag and return null.  */	  int save = errno;	/* Don't want to clobber errno with ENOMEM.  */	  morecore_recursing = 1;	  newinfo = (malloc_info *) irealloc (_heapinfo, newsize * sizeof (malloc_info));	  morecore_recursing = 0;	  if (newinfo == NULL)	    errno = save;	  else	    {	      /* We found some space in core, and realloc has put the old		 table's blocks on the free list.  Now zero the new part		 of the table and install the new table location.  */	      memset (&newinfo[heapsize], 0, (newsize - heapsize) * sizeof (malloc_info));	      _heapinfo = newinfo;	      heapsize = newsize;	      goto got_heap;	    }	}      /* Allocate new space for the malloc info table.  */      while (1)  	{ 	  newinfo = (malloc_info *) align (newsize * sizeof (malloc_info)); 	  /* Did it fail?  */ 	  if (newinfo == NULL) 	    { 	      default_morecore (-size);

⌨️ 快捷键说明

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