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

📄 safemalloc.c

📁 虽然mysql已经在.NET平台上提供了支持
💻 C
字号:
/* Copyright Abandoned 1996 TCX DataKonsult AB & Monty Program KB & Detron HB   This file is public domain and comes with NO WARRANTY of any kind *//* * [This posting refers to an article entitled "oops, corrupted memory * again!" in net.lang.c.  I am posting it here because it is source.] * * My tool for approaching this problem is to build another level of data * abstraction on top of malloc() and free() that implements some checking. * This does a number of things for you: *	- Checks for overruns and underruns on allocated data *	- Keeps track of where in the program the memory was malloc'ed *	- Reports on pieces of memory that were not free'ed *	- Records some statistics such as maximum memory used *	- Marks newly malloc'ed and newly free'ed memory with special values * You can use this scheme to: *	- Find bugs such as overrun, underrun, etc because you know where *	  a piece of data was malloc'ed and where it was free'ed *	- Find bugs where memory was not free'ed *	- Find bugs where newly malloc'ed memory is used without initializing *	- Find bugs where newly free'ed memory is still used *	- Determine how much memory your program really uses *	- and other things *//* * To implement my scheme you must have a C compiler that has __LINE__ and * __FILE__ macros.  If your compiler doesn't have these then (a) buy another: * compilers that do are available on UNIX 4.2bsd based systems and the PC, * and probably on other machines; or (b) change my scheme somehow.  I have * recomendations on both these points if you would like them (e-mail please). * * There are 4 functions in my package: *	char *NEW( uSize )	Allocate memory of uSize bytes *				(equivalent to malloc()) *	char *REA( pPtr, uSize) Allocate memory of uSize bytes, move data and *				free pPtr. *				(equivalent to realloc()) *	FREE( pPtr )		Free memory allocated by NEW *				(equivalent to free()) *	TERMINATE(file)		End system, report errors and stats on file * I personally use two more functions, but have not included them here: *	char *STRSAVE( sPtr )	Save a copy of the string in dynamic memory *	char *RENEW( pPtr, uSize ) *				(equivalent to realloc()) *//* * Memory sub-system, written by Bjorn Benson   Fixed to use my_sys scheme by Michael Widenius */#ifndef SAFEMALLOC#define SAFEMALLOC			/* Get protos from my_sys */#endif#include "mysys_priv.h"#include <m_string.h>#include "my_static.h"#include "mysys_err.h"#define pNext		tInt._pNext#define pPrev		tInt._pPrev#define sFileName	tInt._sFileName#define uLineNum	tInt._uLineNum#define uDataSize	tInt._uDataSize#define lSpecialValue	tInt._lSpecialValue	/* Static functions prototypes */static int check_ptr(my_string where,byte *ptr,const char *sFile, uint uLine);static int _checkchunk(struct remember *pRec, const char *sFile, uint uLine);/* *	Note: both these refer to the NEW'ed *	data only.  They do not include *	malloc() roundoff or the extra *	space required by the remember *	structures. */#define ALLOC_VAL	(uchar) 0xA5	/* NEW'ed memory is filled with this */				/* value so that references to it will	 */				/* end up being very strange.		 */#define FREE_VAL	(uchar) 0x8F	/* FREE'ed memory is filled with this */				/* value so that references to it will	 */				/* also end up being strange.		 */#define MAGICKEY	0x14235296	/* A magic value for underrun key */#define MAGICEND0	0x68		/* Magic values for overrun keys  */#define MAGICEND1	0x34		/*		"		  */#define MAGICEND2	0x7A		/*		"		  */#define MAGICEND3	0x15		/*		"		  */ /* Warning: do not change the MAGICEND? values to */ /* something with the high bit set.  Various C    */ /* compilers (like the 4.2bsd one) do not do the  */ /* sign extension right later on in this code and */ /* you will get erroneous errors.		  *//* * gptr _mymalloc( uint uSize, my_string sFile, uint uLine, MyFlags ) *	Allocate some memory. */gptr _mymalloc (uint uSize, const char *sFile, uint uLine, myf MyFlags){    struct remember *pTmp;    DBUG_ENTER("_mymalloc");    DBUG_PRINT("enter",("Size: %u",uSize));    if (!sf_malloc_quick)      (void) _sanity (sFile, uLine);    /* Allocate the physical memory */    pTmp = (struct remember *) malloc (		sizeof (struct irem)			/* remember data  */		+ sf_malloc_prehunc		+ uSize					/* size requested */		+ 4					/* overrun mark   */		+ sf_malloc_endhunc		);    /* Check if there isn't anymore memory avaiable */    if (pTmp == NULL)    {      if (MyFlags & MY_FAE)	error_handler_hook=fatal_error_handler_hook;      if (MyFlags & (MY_FAE+MY_WME))      {	char buff[SC_MAXWIDTH];	my_errno=errno;	sprintf(buff,"Out of memory at line %d, '%s'", uLine, sFile);	my_message(EE_OUTOFMEMORY,buff,MYF(ME_BELL+ME_WAITTANG));	sprintf(buff,"neaded %d byte (%ldk), memory in use: %ld bytes (%ldk))",		uSize, (uSize + 1023L) / 1024L,		lMaxMemory, (lMaxMemory + 1023L) / 1024L);	my_message(EE_OUTOFMEMORY,buff,MYF(ME_BELL+ME_WAITTANG));      }      DBUG_PRINT("error",("Out of memory, in use: %ld at line %d, '%s'",			  lMaxMemory,uLine, sFile));      if (MyFlags & MY_FAE)	exit(1);      DBUG_RETURN ((gptr) NULL);    }    /* Fill up the structure */    *((long*) ((char*) &pTmp -> lSpecialValue+sf_malloc_prehunc)) = MAGICKEY;    pTmp -> aData[uSize + sf_malloc_prehunc+0] = MAGICEND0;    pTmp -> aData[uSize + sf_malloc_prehunc+1] = MAGICEND1;    pTmp -> aData[uSize + sf_malloc_prehunc+2] = MAGICEND2;    pTmp -> aData[uSize + sf_malloc_prehunc+3] = MAGICEND3;    pTmp -> sFileName = (my_string) sFile;    pTmp -> uLineNum = uLine;    pTmp -> uDataSize = uSize;    pTmp -> pPrev = NULL;    /* Add this remember structure to the linked list */    pthread_mutex_lock(&THR_LOCK_malloc);    if ((pTmp->pNext=pRememberRoot))    {      pRememberRoot -> pPrev = pTmp;    }    pRememberRoot = pTmp;    /* Keep the statistics */    lCurMemory += uSize;    if (lCurMemory > lMaxMemory) {	lMaxMemory = lCurMemory;    }    cNewCount++;    pthread_mutex_unlock(&THR_LOCK_malloc);    /* Set the memory to the aribtrary wierd value */#ifdef HAVE_purify    if (MyFlags & MY_ZEROFILL)#endif      bfill(&pTmp -> aData[sf_malloc_prehunc],uSize,	    (char) (MyFlags & MY_ZEROFILL ? 0 : ALLOC_VAL));    /* Return a pointer to the real data */    DBUG_PRINT("exit",("ptr: %lx",&(pTmp -> aData[sf_malloc_prehunc])));    if (sf_min_adress > &(pTmp -> aData[sf_malloc_prehunc]))      sf_min_adress = &(pTmp -> aData[sf_malloc_prehunc]);    if (sf_max_adress < &(pTmp -> aData[sf_malloc_prehunc]))      sf_max_adress = &(pTmp -> aData[sf_malloc_prehunc]);    DBUG_RETURN ((gptr) &(pTmp -> aData[sf_malloc_prehunc]));}/* *  Allocate some new memory and move old memoryblock there. *  Free then old memoryblock */gptr _myrealloc (register my_string pPtr, register uint uSize,		 const char *sFile, uint uLine, myf MyFlags){  struct remember *pRec;  gptr ptr;  DBUG_ENTER("_myrealloc");  if (!pPtr && (MyFlags & MY_ALLOW_ZERO_PTR))    DBUG_RETURN(_mymalloc(uSize,sFile,uLine,MyFlags));  if (!sf_malloc_quick)    (void) _sanity (sFile, uLine);  if (check_ptr("Reallocating",(byte*) pPtr,sFile,uLine))    DBUG_RETURN((gptr) NULL);  pRec = (struct remember *) (pPtr - sizeof (struct irem)-sf_malloc_prehunc);  if (*((long*) ((char*) &pRec -> lSpecialValue+sf_malloc_prehunc))      != MAGICKEY)  {    fprintf (stderr, "Reallocating unallocated data at line %d, '%s'\n",	     uLine, sFile);    DBUG_PRINT("safe",("Reallocating unallocated data at line %d, '%s'",		       uLine, sFile));    (void) fflush(stderr);    DBUG_RETURN((gptr) NULL);  }  if ((ptr=_mymalloc(uSize,sFile,uLine,MyFlags)))	/* Allocate new area */  {    uSize=min(uSize,pRec-> uDataSize);		/* Move as much as possibly */    memcpy((byte*) ptr,pPtr,(size_t) uSize);	/* Copy old data */    _myfree(pPtr,sFile,uLine,0);		/* Free not needed area */  }  else  {    if (MyFlags & MY_HOLD_ON_ERROR)      DBUG_RETURN(pPtr);    if (MyFlags & MY_FREE_ON_ERROR)      _myfree(pPtr,sFile,uLine,0);  }  DBUG_RETURN(ptr);} /* _myrealloc *//* * void _myfree( my_string pPtr, my_string sFile, uint uLine, myf myflags) *	Deallocate some memory. */void _myfree (gptr pPtr, const char *sFile, uint uLine, myf myflags){  struct remember *pRec;  DBUG_ENTER("_myfree");  DBUG_PRINT("enter",("ptr: %lx",pPtr));  if (!sf_malloc_quick)    (void) _sanity (sFile, uLine);  if (!pPtr && (myflags & MY_ALLOW_ZERO_PTR) ||      check_ptr("Freeing",(byte*) pPtr,sFile,uLine))    DBUG_VOID_RETURN;  /* Calculate the address of the remember structure */  pRec = (struct remember *) ((byte*) pPtr-sizeof(struct irem)-			      sf_malloc_prehunc);  /* Check to make sure that we have a real remember structure	*/  /* Note: this test could fail for four reasons:		*/  /*	(1) The memory was already free'ed			*/  /*	(2) The memory was never new'ed				*/  /*	(3) There was an underrun				*/  /*	(4) A stray pointer hit this location			*/  if (*((long*) ((char*) &pRec -> lSpecialValue+sf_malloc_prehunc))      != MAGICKEY)  {    fprintf (stderr, "Freeing unallocated data at line %d, '%s'\n",	     uLine, sFile);    DBUG_PRINT("safe",("Unallocated data at line %d, '%s'",uLine,sFile));    (void) fflush(stderr);    DBUG_VOID_RETURN;  }  /* Remove this structure from the linked list */  pthread_mutex_lock(&THR_LOCK_malloc);  if (pRec -> pPrev) {    pRec -> pPrev -> pNext = pRec -> pNext;  } else {    pRememberRoot = pRec -> pNext;  }  if (pRec -> pNext) {    pRec -> pNext -> pPrev = pRec -> pPrev;  }  /* Handle the statistics */  lCurMemory -= pRec -> uDataSize;  cNewCount--;  pthread_mutex_unlock(&THR_LOCK_malloc);#ifndef HAVE_purify  /* Mark this data as free'ed */  bfill(&pRec->aData[sf_malloc_prehunc],pRec->uDataSize,(pchar) FREE_VAL);#endif  *((long*) ((char*) &pRec -> lSpecialValue+sf_malloc_prehunc)) = ~MAGICKEY;  /* Actually free the memory */  free ((my_string ) pRec);  DBUG_VOID_RETURN;}	/* Check if we have a wrong  pointer */static int check_ptr(my_string where, byte *ptr, const char *sFile, uint uLine){  if (!ptr)  {    fprintf (stderr, "%s NULL pointer at line %d, '%s'\n",	     where,uLine, sFile);    DBUG_PRINT("safe",("Null pointer at line %d '%s'", uLine, sFile));    (void) fflush(stderr);    return 1;  }#ifndef _MSC_VER  if ((long) ptr & (MY_ALIGN(1,sizeof(char *))-1))  {    fprintf (stderr, "%s wrong aligned pointer at line %d, '%s'\n",	     where,uLine, sFile);    DBUG_PRINT("safe",("Wrong aligned pointer at line %d, '%s'",		       uLine,sFile));    (void) fflush(stderr);    return 1;  }#endif  if (ptr < sf_min_adress || ptr > sf_max_adress)  {    fprintf (stderr, "%s pointer out of range at line %d, '%s'\n",	     where,uLine, sFile);    DBUG_PRINT("safe",("Pointer out of range at line %d '%s'",		       uLine,sFile));    (void) fflush(stderr);    return 1;  }  return 0;}/* * TERMINATE(FILE *file) *	Report on all the memory pieces that have not been *	free'ed as well as the statistics. */void TERMINATE (FILE *file){  struct remember *pPtr;  DBUG_ENTER("TERMINATE");  pthread_mutex_lock(&THR_LOCK_malloc);  /* Report the difference between number of calls to  */  /* NEW and the number of calls to FREE.  >0 means more	 */  /* NEWs than FREEs.  <0, etc.				 */  if (cNewCount) {    fprintf (file, "cNewCount: %d\n", cNewCount);    (void) fflush(file);  }  /* Report on all the memory that was allocated with NEW	 */  /* but not free'ed with FREE.				 */  if (pRememberRoot != NULL) {    fprintf (file, "Memory that was not free'ed:\n");    (void) fflush(file);    DBUG_PRINT("safe",("Memory that was not free'ed:"));  }  pPtr = pRememberRoot;  while (pPtr) {    fprintf (file,	     "\t%6u bytes at 0x%09lx, allocated at line %4d in '%s'\n",	     pPtr -> uDataSize, &(pPtr -> aData[sf_malloc_prehunc]),	     pPtr -> uLineNum, pPtr -> sFileName	     );    DBUG_PRINT("safe",	       ("%6u bytes at 0x%09lx, allocated at line %4d in '%s'",		pPtr -> uDataSize, &(pPtr -> aData[sf_malloc_prehunc]),		pPtr -> uLineNum, pPtr -> sFileName		));    (void) fflush(file);    pPtr = pPtr -> pNext;  }  /* Report the memory usage statistics */  fprintf (file, "Maximum memory usage: %ld bytes (%ldk)\n",	   lMaxMemory, (lMaxMemory + 1023L) / 1024L);  (void) fflush(file);  pthread_mutex_unlock(&THR_LOCK_malloc);  DBUG_VOID_RETURN;}	/* Returns 0 if chunk is ok */static int _checkchunk (register struct remember *pRec, const char *sFile,			uint uLine){  reg1 uint uSize;  reg2 my_string magicp;  reg3 int flag=0;  /* Check for a possible underrun */  if (*((long*) ((char*) &pRec -> lSpecialValue+sf_malloc_prehunc))      != MAGICKEY)  {    fprintf (stderr, "Memory allocated at %s:%d was underrun,",	     pRec -> sFileName, pRec -> uLineNum);    fprintf (stderr, " discovered at %s:%d\n", sFile, uLine);    (void) fflush(stderr);    DBUG_PRINT("safe",("Underrun at %lx, allocated at %s:%d",		       &(pRec -> aData[sf_malloc_prehunc]),		       pRec -> sFileName,		       pRec -> uLineNum));    flag=1;  }  /* Check for a possible overrun */  uSize = pRec -> uDataSize;  magicp = &(pRec -> aData[uSize+sf_malloc_prehunc]);  if (*magicp++ != MAGICEND0 ||      *magicp++ != MAGICEND1 ||      *magicp++ != MAGICEND2 ||      *magicp++ != MAGICEND3)  {    fprintf (stderr, "Memory allocated at %s:%d was overrun,",	     pRec -> sFileName, pRec -> uLineNum);    fprintf (stderr, " discovered at '%s:%d'\n", sFile, uLine);    (void) fflush(stderr);    DBUG_PRINT("safe",("Overrun at %lx, allocated at %s:%d",		       &(pRec -> aData[sf_malloc_prehunc]),		       pRec -> sFileName,		       pRec -> uLineNum));    flag=1;  }  return(flag);}	/* Returns how many wrong chunks */int _sanity (const char *sFile, uint uLine){  reg1 struct remember *pTmp;  reg2 int flag=0;  pthread_mutex_lock(&THR_LOCK_malloc);  for (pTmp = pRememberRoot; pTmp != NULL; pTmp = pTmp -> pNext)    flag+=_checkchunk (pTmp, sFile, uLine);  pthread_mutex_unlock(&THR_LOCK_malloc);  return flag;} /* _sanity */	/* malloc and copy */gptr _my_memdup(const byte *from, uint length, const char *sFile, uint uLine,		myf MyFlags){  gptr ptr;  if ((ptr=_mymalloc(length,sFile,uLine,MyFlags)) != 0)    memcpy((byte*) ptr, (byte*) from,(size_t) length);  return(ptr);} /*_my_memdup */my_string _my_strdup(const char *from, const char *sFile, uint uLine,		     myf MyFlags){  gptr ptr;  uint length=(uint) strlen(from)+1;  if ((ptr=_mymalloc(length,sFile,uLine,MyFlags)) != 0)    memcpy((byte*) ptr, (byte*) from,(size_t) length);  return((my_string) ptr);} /* _my_strdup */

⌨️ 快捷键说明

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