diff options
Diffstat (limited to 'mysys/safemalloc.c')
-rw-r--r-- | mysys/safemalloc.c | 262 |
1 files changed, 98 insertions, 164 deletions
diff --git a/mysys/safemalloc.c b/mysys/safemalloc.c index 074afe27500..9615126f237 100644 --- a/mysys/safemalloc.c +++ b/mysys/safemalloc.c @@ -15,53 +15,50 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* - * [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 - */ + + [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()) + +*/ #ifndef SAFEMALLOC #define SAFEMALLOC /* Get protos from my_sys */ @@ -74,24 +71,20 @@ ulonglong safemalloc_mem_limit = ~(ulonglong)0; -#ifdef THREAD -pthread_t shutdown_th,main_th,signal_th; -#endif - #define pNext tInt._pNext #define pPrev tInt._pPrev #define sFileName tInt._sFileName #define uLineNum tInt._uLineNum #define uDataSize tInt._uDataSize -#define thread_id tInt.thread_id #define lSpecialValue tInt._lSpecialValue #ifndef PEDANTIC_SAFEMALLOC -static int sf_malloc_tampered = 0; /* set to 1 after TERMINATE() if we had - to fiddle with cNewCount and the linked - list of blocks so that _sanity() will - not fuss when it is not supposed to - */ +/* + Set to 1 after TERMINATE() if we had to fiddle with cNewCount and + the linked list of blocks so that _sanity() will not fuss when it + is not supposed to +*/ +static int sf_malloc_tampered = 0; #endif @@ -102,37 +95,37 @@ static int check_ptr(const char *where, byte *ptr, const char *sFile, 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. */ + 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. +*/ +/* + NEW'ed memory is filled with this value so that references to it will + end up being very strange. +*/ +#define ALLOC_VAL (uchar) 0xA5 +/* + FEEE'ed memory is filled with this value so that references to it will + end up being very strange. +*/ +#define FREE_VAL (uchar) 0x8F #define MAGICKEY 0x14235296 /* A magic value for underrun key */ + +/* + 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. +*/ + #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. - */ +/* Allocate some memory. */ gptr _mymalloc (uint uSize, const char *sFile, uint uLine, myf MyFlags) { @@ -144,18 +137,19 @@ gptr _mymalloc (uint uSize, const char *sFile, uint uLine, myf MyFlags) if (!sf_malloc_quick) (void) _sanity (sFile, uLine); - if(uSize + lCurMemory > safemalloc_mem_limit) + if (uSize + lCurMemory > safemalloc_mem_limit) pTmp = 0; else + { /* Allocate the physical memory */ pTmp = (struct remember *) malloc ( - sizeof (struct irem) /* remember data */ + ALIGN_SIZE(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) { @@ -188,9 +182,6 @@ gptr _mymalloc (uint uSize, const char *sFile, uint uLine, myf MyFlags) pTmp -> sFileName = (my_string) sFile; pTmp -> uLineNum = uLine; pTmp -> uDataSize = uSize; -#ifdef THREAD - pTmp->thread_id = pthread_self(); -#endif pTmp -> pPrev = NULL; /* Add this remember structure to the linked list */ @@ -225,9 +216,9 @@ gptr _mymalloc (uint uSize, const char *sFile, uint uLine, myf MyFlags) } /* - * Allocate some new memory and move old memoryblock there. - * Free then old memoryblock - */ + Allocate some new memory and move old memoryblock there. + Free then old memoryblock +*/ gptr _myrealloc (register gptr pPtr, register uint uSize, const char *sFile, uint uLine, myf MyFlags) @@ -245,7 +236,7 @@ gptr _myrealloc (register gptr pPtr, register uint uSize, if (check_ptr("Reallocating",(byte*) pPtr,sFile,uLine)) DBUG_RETURN((gptr) NULL); - pRec = (struct remember *) ((char*) pPtr - sizeof (struct irem)- + pRec = (struct remember *) ((char*) pPtr - ALIGN_SIZE(sizeof(struct irem))- sf_malloc_prehunc); if (*((long*) ((char*) &pRec -> lSpecialValue+sf_malloc_prehunc)) != MAGICKEY) @@ -258,7 +249,7 @@ gptr _myrealloc (register gptr pPtr, register uint uSize, DBUG_RETURN((gptr) NULL); } - if ((ptr=_mymalloc(uSize,sFile,uLine,MyFlags))) /* Allocate new area */ + 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 */ @@ -275,10 +266,7 @@ gptr _myrealloc (register gptr pPtr, register uint uSize, } /* _myrealloc */ -/* - * void _myfree( my_string pPtr, my_string sFile, uint uLine, myf myflags) - * Deallocate some memory. - */ +/* Deallocate some memory. */ void _myfree (gptr pPtr, const char *sFile, uint uLine, myf myflags) { @@ -294,15 +282,17 @@ void _myfree (gptr pPtr, const char *sFile, uint uLine, myf myflags) DBUG_VOID_RETURN; /* Calculate the address of the remember structure */ - pRec = (struct remember *) ((byte*) pPtr-sizeof(struct irem)- + pRec = (struct remember *) ((byte*) pPtr- ALIGN_SIZE(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 */ + /* + 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) @@ -354,7 +344,7 @@ static int check_ptr(const char *where, byte *ptr, const char *sFile, return 1; } #ifndef _MSC_VER - if ((long) ptr & (MY_ALIGN(1,sizeof(char *))-1)) + if ((long) ptr & (ALIGN_SIZE(1)-1)) { fprintf (stderr, "%s wrong aligned pointer at line %d, '%s'\n", where,uLine, sFile); @@ -376,24 +366,11 @@ static int check_ptr(const char *where, byte *ptr, const char *sFile, return 0; } -#ifdef THREAD -static int legal_leak(struct remember* pPtr) -{ - return pthread_self() == pPtr->thread_id || main_th == pPtr->thread_id - || shutdown_th == pPtr->thread_id - || signal_th == pPtr->thread_id; -} -#else -static int legal_leak(struct remember* pPtr) -{ - return 1; -} -#endif /* - * TERMINATE(FILE *file) - * Report on all the memory pieces that have not been - * free'ed as well as the statistics. + TERMINATE(FILE *file) + Report on all the memory pieces that have not been + free'ed as well as the statistics. */ void TERMINATE (FILE *file) @@ -408,48 +385,6 @@ void TERMINATE (FILE *file) NEWs than FREEs. <0, etc. */ -#if !defined(PEDANTIC_SAFEMALLOC) && defined(THREAD) - /* - Avoid false alarms for blocks that we cannot free before my_end() - This does miss some positives, but that is ok. This will only miss - failures to free things allocated in the main thread which - performs only one-time allocations. If you really need to - debug memory allocations in the main thread, - #define PEDANTIC_SAFEMALLOC - */ - if ((pPtr=pRememberRoot)) - { - while (pPtr) - { - if (legal_leak(pPtr)) - { - sf_malloc_tampered=1; - cNewCount--; - lCurMemory -= pPtr->uDataSize; - if (pPtr->pPrev) - { - struct remember* tmp; - tmp = pPtr->pPrev->pNext = pPtr->pNext; - if (tmp) - tmp->pPrev = pPtr->pPrev; - pPtr->pNext = pPtr->pPrev = 0; - pPtr = tmp; - } - else - { - pRememberRoot = pPtr->pNext; - pPtr->pNext = pPtr->pPrev = 0; - pPtr = pRememberRoot; - if (pPtr) - pPtr->pPrev=0; - } - } - else - pPtr = pPtr->pNext; - } - } -#endif - if (cNewCount) { if (file) @@ -460,8 +395,10 @@ void TERMINATE (FILE *file) DBUG_PRINT("safe",("cNewCount: %d",cNewCount)); } - /* Report on all the memory that was allocated with NEW */ - /* but not free'ed with FREE. */ + /* + Report on all the memory that was allocated with NEW + but not free'ed with FREE. + */ if ((pPtr=pRememberRoot)) { @@ -480,9 +417,6 @@ void TERMINATE (FILE *file) pPtr -> uDataSize, (ulong) &(pPtr -> aData[sf_malloc_prehunc]), pPtr -> uLineNum, pPtr -> sFileName); -#ifdef THREAD - fprintf(file, " in thread %ld", pPtr->thread_id); -#endif fprintf(file, "\n"); (void) fflush(file); } |