mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-07 02:42:48 +03:00
Add some more logging to the malloc system used when SQLITE_MEMDEBUG is defined. (CVS 4901)
FossilOrigin-Name: 79738f582fbac87f2d335e0c6b7f53e3054b41ba
This commit is contained in:
@@ -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++){
|
||||
|
Reference in New Issue
Block a user