📄 test_malloc.c
字号:
} zBin = p; while( size>0 ){ if( size>(sizeof(zHex)-1)/2 ){ n = (sizeof(zHex)-1)/2; }else{ n = size; } memcpy(zHex, zBin, n); zBin += n; size -= n; sqlite3TestBinToHex(zHex, n); Tcl_AppendResult(interp, zHex, (char*)0); } return TCL_OK;}/*** Usage: sqlite3_memory_used**** Raw test interface for sqlite3_memory_used().*/static int test_memory_used( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]){ Tcl_SetObjResult(interp, Tcl_NewWideIntObj(sqlite3_memory_used())); return TCL_OK;}/*** Usage: sqlite3_memory_highwater ?RESETFLAG?**** Raw test interface for sqlite3_memory_highwater().*/static int test_memory_highwater( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]){ int resetFlag = 0; if( objc!=1 && objc!=2 ){ Tcl_WrongNumArgs(interp, 1, objv, "?RESET?"); return TCL_ERROR; } if( objc==2 ){ if( Tcl_GetBooleanFromObj(interp, objv[1], &resetFlag) ) return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewWideIntObj(sqlite3_memory_highwater(resetFlag))); return TCL_OK;}/*** Usage: sqlite3_memdebug_backtrace DEPTH**** Set the depth of backtracing. If SQLITE_MEMDEBUG is not defined** then this routine is a no-op.*/static int test_memdebug_backtrace( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]){ int depth; if( objc!=2 ){ Tcl_WrongNumArgs(interp, 1, objv, "DEPT"); return TCL_ERROR; } if( Tcl_GetIntFromObj(interp, objv[1], &depth) ) return TCL_ERROR;#ifdef SQLITE_MEMDEBUG { extern void sqlite3MemdebugBacktrace(int); sqlite3MemdebugBacktrace(depth); }#endif return TCL_OK;}/*** Usage: sqlite3_memdebug_dump FILENAME**** Write a summary of unfreed memory to FILENAME.*/static int test_memdebug_dump( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]){ if( objc!=2 ){ Tcl_WrongNumArgs(interp, 1, objv, "FILENAME"); return TCL_ERROR; }#if defined(SQLITE_MEMDEBUG) || defined(SQLITE_MEMORY_SIZE) \ || defined(SQLITE_POW2_MEMORY_SIZE) { extern void sqlite3MemdebugDump(const char*); sqlite3MemdebugDump(Tcl_GetString(objv[1])); }#endif return TCL_OK;}/*** Usage: sqlite3_memdebug_malloc_count**** Return the total number of times malloc() has been called.*/static int test_memdebug_malloc_count( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]){ int nMalloc = -1; if( objc!=1 ){ Tcl_WrongNumArgs(interp, 1, objv, ""); return TCL_ERROR; }#if defined(SQLITE_MEMDEBUG) { extern int sqlite3MemdebugMallocCount(); nMalloc = sqlite3MemdebugMallocCount(); }#endif Tcl_SetObjResult(interp, Tcl_NewIntObj(nMalloc)); return TCL_OK;}/*** Usage: sqlite3_memdebug_fail COUNTER ?OPTIONS?**** where options are:**** -repeat <count>** -benigncnt <varname>**** Arrange for a simulated malloc() failure after COUNTER successes.** If a repeat count is specified, the fault is repeated that many** times.**** Each call to this routine overrides the prior counter value.** This routine returns the number of simulated failures that have** happened since the previous call to this routine.**** To disable simulated failures, use a COUNTER of -1.*/static int test_memdebug_fail( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]){ int ii; int iFail; int nRepeat = 1; Tcl_Obj *pBenignCnt = 0; int nBenign; int nFail = 0; if( objc<2 ){ Tcl_WrongNumArgs(interp, 1, objv, "COUNTER ?OPTIONS?"); return TCL_ERROR; } if( Tcl_GetIntFromObj(interp, objv[1], &iFail) ) return TCL_ERROR; for(ii=2; ii<objc; ii+=2){ int nOption; char *zOption = Tcl_GetStringFromObj(objv[ii], &nOption); char *zErr = 0; if( nOption>1 && strncmp(zOption, "-repeat", nOption)==0 ){ if( ii==(objc-1) ){ zErr = "option requires an argument: "; }else{ if( Tcl_GetIntFromObj(interp, objv[ii+1], &nRepeat) ){ return TCL_ERROR; } } }else if( nOption>1 && strncmp(zOption, "-benigncnt", nOption)==0 ){ if( ii==(objc-1) ){ zErr = "option requires an argument: "; }else{ pBenignCnt = objv[ii+1]; } }else{ zErr = "unknown option: "; } if( zErr ){ Tcl_AppendResult(interp, zErr, zOption, 0); return TCL_ERROR; } } nBenign = faultsimBenignFailures(); nFail = faultsimFailures(); faultsimConfig(iFail, nRepeat); if( pBenignCnt ){ Tcl_ObjSetVar2(interp, pBenignCnt, 0, Tcl_NewIntObj(nBenign), 0); } Tcl_SetObjResult(interp, Tcl_NewIntObj(nFail)); return TCL_OK;}/*** Usage: sqlite3_memdebug_pending**** Return the number of malloc() calls that will succeed before a ** simulated failure occurs. A negative return value indicates that** no malloc() failure is scheduled.*/static int test_memdebug_pending( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]){ int nPending; if( objc!=1 ){ Tcl_WrongNumArgs(interp, 1, objv, ""); return TCL_ERROR; } nPending = faultsimPending(); Tcl_SetObjResult(interp, Tcl_NewIntObj(nPending)); return TCL_OK;}/*** Usage: sqlite3_memdebug_settitle TITLE**** Set a title string stored with each allocation. The TITLE is** typically the name of the test that was running when the** allocation occurred. The TITLE is stored with the allocation** and can be used to figure out which tests are leaking memory.**** Each title overwrite the previous.*/static int test_memdebug_settitle( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]){ const char *zTitle; if( objc!=2 ){ Tcl_WrongNumArgs(interp, 1, objv, "TITLE"); return TCL_ERROR; } zTitle = Tcl_GetString(objv[1]);#ifdef SQLITE_MEMDEBUG { extern int sqlite3MemdebugSettitle(const char*); sqlite3MemdebugSettitle(zTitle); }#endif return TCL_OK;}#define MALLOC_LOG_FRAMES 10 static Tcl_HashTable aMallocLog;static int mallocLogEnabled = 0;typedef struct MallocLog MallocLog;struct MallocLog { int nCall; int nByte;};#ifdef SQLITE_MEMDEBUGstatic 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; }}#endif /* SQLITE_MEMDEBUG */static void test_memdebug_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);}static int test_memdebug_log( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]){ static int isInit = 0; int iSub; static const char *MB_strs[] = { "start", "stop", "dump", "clear", "sync" }; enum MB_enum { MB_LOG_START, MB_LOG_STOP, MB_LOG_DUMP, MB_LOG_CLEAR, MB_LOG_SYNC }; 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: { test_memdebug_log_clear(); break; } case MB_LOG_SYNC: {#ifdef SQLITE_MEMDEBUG extern void sqlite3MemdebugSync(); test_memdebug_log_clear(); mallocLogEnabled = 1; sqlite3MemdebugSync();#endif break; } } return TCL_OK;}/*** Usage: sqlite3_config_scratch SIZE N**** Set the scratch memory buffer using SQLITE_CONFIG_SCRATCH.** The buffer is static and is of limited size. N might be** adjusted downward as needed to accomodate the requested size.** The revised value of N is returned.**** A negative SIZE causes the buffer pointer to be NULL.*/static int test_config_scratch( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]){ int sz, N, rc; Tcl_Obj *pResult; static char *buf = 0; if( objc!=3 ){ Tcl_WrongNumArgs(interp, 1, objv, "SIZE N"); return TCL_ERROR; } if( Tcl_GetIntFromObj(interp, objv[1], &sz) ) return TCL_ERROR; if( Tcl_GetIntFromObj(interp, objv[2], &N) ) return TCL_ERROR; free(buf); if( sz<0 ){ buf = 0; rc = sqlite3_config(SQLITE_CONFIG_SCRATCH, 0, 0, 0); }else{ buf = malloc( sz*N + 1 ); rc = sqlite3_config(SQLITE_CONFIG_SCRATCH, buf, sz, N); } pResult = Tcl_NewObj(); Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(rc)); Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(N));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -