diff options
author | danielk1977 <danielk1977@noemail.net> | 2008-03-21 14:22:44 +0000 |
---|---|---|
committer | danielk1977 <danielk1977@noemail.net> | 2008-03-21 14:22:44 +0000 |
commit | 6f332c18d91531fbdc283eceacfc20ab414b77a9 (patch) | |
tree | 76e38d6d4c91ac6ed0414ad9e5b70aa0b2775e8b /src/test_malloc.c | |
parent | f47ce56c493d91554f52ff39f5bd9af258f2985d (diff) | |
download | sqlite-6f332c18d91531fbdc283eceacfc20ab414b77a9.tar.gz sqlite-6f332c18d91531fbdc283eceacfc20ab414b77a9.zip |
Add some more logging to the malloc system used when SQLITE_MEMDEBUG is defined. (CVS 4901)
FossilOrigin-Name: 79738f582fbac87f2d335e0c6b7f53e3054b41ba
Diffstat (limited to 'src/test_malloc.c')
-rw-r--r-- | src/test_malloc.c | 127 |
1 files changed, 126 insertions, 1 deletions
diff --git a/src/test_malloc.c b/src/test_malloc.c index c0daf4690..ce2f718be 100644 --- a/src/test_malloc.c +++ b/src/test_malloc.c @@ -13,7 +13,7 @@ ** This file contains code used to implement test interfaces to the ** memory allocation subsystem. ** -** $Id: test_malloc.c,v 1.17 2008/03/18 13:01:38 drh Exp $ +** $Id: test_malloc.c,v 1.18 2008/03/21 14:22:44 danielk1977 Exp $ */ #include "sqliteInt.h" #include "tcl.h" @@ -507,6 +507,130 @@ static int test_memdebug_settitle( return TCL_OK; } +#define MALLOC_LOG_FRAMES 5 +static Tcl_HashTable aMallocLog; +static int mallocLogEnabled = 0; + +typedef struct MallocLog MallocLog; +struct MallocLog { + int nCall; + int nByte; +}; + +static void test_memdebug_callback(int nByte, int nFrame, void **aFrame){ + if( mallocLogEnabled ){ + MallocLog *pLog; + Tcl_HashEntry *pEntry; + int isNew; + + int aKey[MALLOC_LOG_FRAMES]; + int nKey = sizeof(int)*MALLOC_LOG_FRAMES; + + memset(aKey, 0, nKey); + if( (sizeof(void*)*nFrame)<nKey ){ + nKey = nFrame*sizeof(void*); + } + memcpy(aKey, aFrame, nKey); + + pEntry = Tcl_CreateHashEntry(&aMallocLog, (const char *)aKey, &isNew); + if( isNew ){ + pLog = (MallocLog *)Tcl_Alloc(sizeof(MallocLog)); + memset(pLog, 0, sizeof(MallocLog)); + Tcl_SetHashValue(pEntry, (ClientData)pLog); + }else{ + pLog = (MallocLog *)Tcl_GetHashValue(pEntry); + } + + pLog->nCall++; + pLog->nByte += nByte; + } +} + +static int test_memdebug_log( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + static int isInit = 0; + int iSub; + + enum MB_enum { MB_LOG_START, MB_LOG_STOP, MB_LOG_DUMP, MB_LOG_CLEAR }; + static const char *MB_strs[] = { "start", "stop", "dump", "clear" }; + + if( !isInit ){ +#ifdef SQLITE_MEMDEBUG + extern void sqlite3MemdebugBacktraceCallback( + void (*xBacktrace)(int, int, void **)); + sqlite3MemdebugBacktraceCallback(test_memdebug_callback); +#endif + Tcl_InitHashTable(&aMallocLog, MALLOC_LOG_FRAMES); + isInit = 1; + } + + if( objc<2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "SUB-COMMAND ..."); + } + if( Tcl_GetIndexFromObj(interp, objv[1], MB_strs, "sub-command", 0, &iSub) ){ + return TCL_ERROR; + } + + switch( (enum MB_enum)iSub ){ + case MB_LOG_START: + mallocLogEnabled = 1; + break; + case MB_LOG_STOP: + mallocLogEnabled = 0; + break; + case MB_LOG_DUMP: { + Tcl_HashSearch search; + Tcl_HashEntry *pEntry; + Tcl_Obj *pRet = Tcl_NewObj(); + + assert(sizeof(int)==sizeof(void*)); + + for( + pEntry=Tcl_FirstHashEntry(&aMallocLog, &search); + pEntry; + pEntry=Tcl_NextHashEntry(&search) + ){ + Tcl_Obj *apElem[MALLOC_LOG_FRAMES+2]; + MallocLog *pLog = (MallocLog *)Tcl_GetHashValue(pEntry); + int *aKey = (int *)Tcl_GetHashKey(&aMallocLog, pEntry); + int ii; + + apElem[0] = Tcl_NewIntObj(pLog->nCall); + apElem[1] = Tcl_NewIntObj(pLog->nByte); + for(ii=0; ii<MALLOC_LOG_FRAMES; ii++){ + apElem[ii+2] = Tcl_NewIntObj(aKey[ii]); + } + + Tcl_ListObjAppendElement(interp, pRet, + Tcl_NewListObj(MALLOC_LOG_FRAMES+2, apElem) + ); + } + + Tcl_SetObjResult(interp, pRet); + break; + } + case MB_LOG_CLEAR: { + Tcl_HashSearch search; + Tcl_HashEntry *pEntry; + for( + pEntry=Tcl_FirstHashEntry(&aMallocLog, &search); + pEntry; + pEntry=Tcl_NextHashEntry(&search) + ){ + MallocLog *pLog = (MallocLog *)Tcl_GetHashValue(pEntry); + Tcl_Free((char *)pLog); + } + Tcl_DeleteHashTable(&aMallocLog); + Tcl_InitHashTable(&aMallocLog, MALLOC_LOG_FRAMES); + } + } + + return TCL_OK; +} /* ** Register commands with the TCL interpreter. @@ -529,6 +653,7 @@ int Sqlitetest_malloc_Init(Tcl_Interp *interp){ { "sqlite3_memdebug_pending", test_memdebug_pending }, { "sqlite3_memdebug_settitle", test_memdebug_settitle }, { "sqlite3_memdebug_malloc_count", test_memdebug_malloc_count }, + { "sqlite3_memdebug_log", test_memdebug_log }, }; int i; for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ |