12f999a67Sdrh /* 22f999a67Sdrh ** 2007 August 15 32f999a67Sdrh ** 42f999a67Sdrh ** The author disclaims copyright to this source code. In place of 52f999a67Sdrh ** a legal notice, here is a blessing: 62f999a67Sdrh ** 72f999a67Sdrh ** May you do good and not evil. 82f999a67Sdrh ** May you find forgiveness for yourself and forgive others. 92f999a67Sdrh ** May you share freely, never taking more than you give. 102f999a67Sdrh ** 112f999a67Sdrh ************************************************************************* 122f999a67Sdrh ** 132f999a67Sdrh ** This file contains code used to implement test interfaces to the 142f999a67Sdrh ** memory allocation subsystem. 152f999a67Sdrh ** 16*643167ffSdrh ** $Id: test_malloc.c,v 1.10 2008/01/22 21:30:53 drh Exp $ 172f999a67Sdrh */ 182f999a67Sdrh #include "sqliteInt.h" 192f999a67Sdrh #include "tcl.h" 202f999a67Sdrh #include <stdlib.h> 212f999a67Sdrh #include <string.h> 222f999a67Sdrh #include <assert.h> 232f999a67Sdrh 242f999a67Sdrh /* 252f999a67Sdrh ** Transform pointers to text and back again 262f999a67Sdrh */ 272f999a67Sdrh static void pointerToText(void *p, char *z){ 282f999a67Sdrh static const char zHex[] = "0123456789abcdef"; 292f999a67Sdrh int i, k; 304a50aac5Sdrh unsigned int u; 314a50aac5Sdrh sqlite3_uint64 n; 324a50aac5Sdrh if( sizeof(n)==sizeof(p) ){ 334a50aac5Sdrh memcpy(&n, &p, sizeof(p)); 344a50aac5Sdrh }else if( sizeof(u)==sizeof(p) ){ 354a50aac5Sdrh memcpy(&u, &p, sizeof(u)); 364a50aac5Sdrh n = u; 374a50aac5Sdrh }else{ 384a50aac5Sdrh assert( 0 ); 394a50aac5Sdrh } 402f999a67Sdrh for(i=0, k=sizeof(p)*2-1; i<sizeof(p)*2; i++, k--){ 412f999a67Sdrh z[k] = zHex[n&0xf]; 422f999a67Sdrh n >>= 4; 432f999a67Sdrh } 442f999a67Sdrh z[sizeof(p)*2] = 0; 452f999a67Sdrh } 462f999a67Sdrh static int hexToInt(int h){ 472f999a67Sdrh if( h>='0' && h<='9' ){ 482f999a67Sdrh return h - '0'; 492f999a67Sdrh }else if( h>='a' && h<='f' ){ 502f999a67Sdrh return h - 'a' + 10; 512f999a67Sdrh }else{ 522f999a67Sdrh return -1; 532f999a67Sdrh } 542f999a67Sdrh } 552f999a67Sdrh static int textToPointer(const char *z, void **pp){ 562f999a67Sdrh sqlite3_uint64 n = 0; 572f999a67Sdrh int i; 584a50aac5Sdrh unsigned int u; 592f999a67Sdrh for(i=0; i<sizeof(void*)*2 && z[0]; i++){ 602f999a67Sdrh int v; 612f999a67Sdrh v = hexToInt(*z++); 622f999a67Sdrh if( v<0 ) return TCL_ERROR; 632f999a67Sdrh n = n*16 + v; 642f999a67Sdrh } 652f999a67Sdrh if( *z!=0 ) return TCL_ERROR; 664a50aac5Sdrh if( sizeof(n)==sizeof(*pp) ){ 674a50aac5Sdrh memcpy(pp, &n, sizeof(n)); 684a50aac5Sdrh }else if( sizeof(u)==sizeof(*pp) ){ 694a50aac5Sdrh u = (unsigned int)n; 704a50aac5Sdrh memcpy(pp, &u, sizeof(u)); 714a50aac5Sdrh }else{ 724a50aac5Sdrh assert( 0 ); 734a50aac5Sdrh } 742f999a67Sdrh return TCL_OK; 752f999a67Sdrh } 762f999a67Sdrh 772f999a67Sdrh /* 782f999a67Sdrh ** Usage: sqlite3_malloc NBYTES 792f999a67Sdrh ** 802f999a67Sdrh ** Raw test interface for sqlite3_malloc(). 812f999a67Sdrh */ 822f999a67Sdrh static int test_malloc( 832f999a67Sdrh void * clientData, 842f999a67Sdrh Tcl_Interp *interp, 852f999a67Sdrh int objc, 862f999a67Sdrh Tcl_Obj *CONST objv[] 872f999a67Sdrh ){ 882f999a67Sdrh int nByte; 892f999a67Sdrh void *p; 902f999a67Sdrh char zOut[100]; 912f999a67Sdrh if( objc!=2 ){ 922f999a67Sdrh Tcl_WrongNumArgs(interp, 1, objv, "NBYTES"); 932f999a67Sdrh return TCL_ERROR; 942f999a67Sdrh } 952f999a67Sdrh if( Tcl_GetIntFromObj(interp, objv[1], &nByte) ) return TCL_ERROR; 962f999a67Sdrh p = sqlite3_malloc((unsigned)nByte); 972f999a67Sdrh pointerToText(p, zOut); 982f999a67Sdrh Tcl_AppendResult(interp, zOut, NULL); 992f999a67Sdrh return TCL_OK; 1002f999a67Sdrh } 1012f999a67Sdrh 1022f999a67Sdrh /* 1032f999a67Sdrh ** Usage: sqlite3_realloc PRIOR NBYTES 1042f999a67Sdrh ** 1052f999a67Sdrh ** Raw test interface for sqlite3_realloc(). 1062f999a67Sdrh */ 1072f999a67Sdrh static int test_realloc( 1082f999a67Sdrh void * clientData, 1092f999a67Sdrh Tcl_Interp *interp, 1102f999a67Sdrh int objc, 1112f999a67Sdrh Tcl_Obj *CONST objv[] 1122f999a67Sdrh ){ 1132f999a67Sdrh int nByte; 1142f999a67Sdrh void *pPrior, *p; 1152f999a67Sdrh char zOut[100]; 1162f999a67Sdrh if( objc!=3 ){ 1172f999a67Sdrh Tcl_WrongNumArgs(interp, 1, objv, "PRIOR NBYTES"); 1182f999a67Sdrh return TCL_ERROR; 1192f999a67Sdrh } 1202f999a67Sdrh if( Tcl_GetIntFromObj(interp, objv[2], &nByte) ) return TCL_ERROR; 1212f999a67Sdrh if( textToPointer(Tcl_GetString(objv[1]), &pPrior) ){ 1222f999a67Sdrh Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0); 1232f999a67Sdrh return TCL_ERROR; 1242f999a67Sdrh } 1252f999a67Sdrh p = sqlite3_realloc(pPrior, (unsigned)nByte); 1262f999a67Sdrh pointerToText(p, zOut); 1272f999a67Sdrh Tcl_AppendResult(interp, zOut, NULL); 1282f999a67Sdrh return TCL_OK; 1292f999a67Sdrh } 1302f999a67Sdrh 1312f999a67Sdrh 1322f999a67Sdrh /* 1332f999a67Sdrh ** Usage: sqlite3_free PRIOR 1342f999a67Sdrh ** 1352f999a67Sdrh ** Raw test interface for sqlite3_free(). 1362f999a67Sdrh */ 1372f999a67Sdrh static int test_free( 1382f999a67Sdrh void * clientData, 1392f999a67Sdrh Tcl_Interp *interp, 1402f999a67Sdrh int objc, 1412f999a67Sdrh Tcl_Obj *CONST objv[] 1422f999a67Sdrh ){ 1432f999a67Sdrh void *pPrior; 1442f999a67Sdrh if( objc!=2 ){ 1452f999a67Sdrh Tcl_WrongNumArgs(interp, 1, objv, "PRIOR"); 1462f999a67Sdrh return TCL_ERROR; 1472f999a67Sdrh } 1482f999a67Sdrh if( textToPointer(Tcl_GetString(objv[1]), &pPrior) ){ 1492f999a67Sdrh Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0); 1502f999a67Sdrh return TCL_ERROR; 1512f999a67Sdrh } 1522f999a67Sdrh sqlite3_free(pPrior); 1532f999a67Sdrh return TCL_OK; 1542f999a67Sdrh } 1552f999a67Sdrh 1562f999a67Sdrh /* 1579c7a60dfSdrh ** These routines are in test_hexio.c 1589c7a60dfSdrh */ 1599c7a60dfSdrh int sqlite3TestHexToBin(const char *, int, char *); 1609c7a60dfSdrh int sqlite3TestBinToHex(char*,int); 1619c7a60dfSdrh 1629c7a60dfSdrh /* 1639c7a60dfSdrh ** Usage: memset ADDRESS SIZE HEX 1649c7a60dfSdrh ** 1659c7a60dfSdrh ** Set a chunk of memory (obtained from malloc, probably) to a 1669c7a60dfSdrh ** specified hex pattern. 1679c7a60dfSdrh */ 1689c7a60dfSdrh static int test_memset( 1699c7a60dfSdrh void * clientData, 1709c7a60dfSdrh Tcl_Interp *interp, 1719c7a60dfSdrh int objc, 1729c7a60dfSdrh Tcl_Obj *CONST objv[] 1739c7a60dfSdrh ){ 1749c7a60dfSdrh void *p; 1759c7a60dfSdrh int size, n, i; 1769c7a60dfSdrh char *zHex; 1779c7a60dfSdrh char *zOut; 1789c7a60dfSdrh char zBin[100]; 1799c7a60dfSdrh 1809c7a60dfSdrh if( objc!=4 ){ 1819c7a60dfSdrh Tcl_WrongNumArgs(interp, 1, objv, "ADDRESS SIZE HEX"); 1829c7a60dfSdrh return TCL_ERROR; 1839c7a60dfSdrh } 1849c7a60dfSdrh if( textToPointer(Tcl_GetString(objv[1]), &p) ){ 1859c7a60dfSdrh Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0); 1869c7a60dfSdrh return TCL_ERROR; 1879c7a60dfSdrh } 1889c7a60dfSdrh if( Tcl_GetIntFromObj(interp, objv[2], &size) ){ 1899c7a60dfSdrh return TCL_ERROR; 1909c7a60dfSdrh } 1919c7a60dfSdrh if( size<=0 ){ 1929c7a60dfSdrh Tcl_AppendResult(interp, "size must be positive", (char*)0); 1939c7a60dfSdrh return TCL_ERROR; 1949c7a60dfSdrh } 1959c7a60dfSdrh zHex = Tcl_GetStringFromObj(objv[3], &n); 1969c7a60dfSdrh if( n>sizeof(zBin)*2 ) n = sizeof(zBin)*2; 1979c7a60dfSdrh n = sqlite3TestHexToBin(zHex, n, zBin); 1989c7a60dfSdrh if( n==0 ){ 1999c7a60dfSdrh Tcl_AppendResult(interp, "no data", (char*)0); 2009c7a60dfSdrh return TCL_ERROR; 2019c7a60dfSdrh } 2029c7a60dfSdrh zOut = p; 2039c7a60dfSdrh for(i=0; i<size; i++){ 2049c7a60dfSdrh zOut[i] = zBin[i%n]; 2059c7a60dfSdrh } 2069c7a60dfSdrh return TCL_OK; 2079c7a60dfSdrh } 2089c7a60dfSdrh 2099c7a60dfSdrh /* 2109c7a60dfSdrh ** Usage: memget ADDRESS SIZE 2119c7a60dfSdrh ** 2129c7a60dfSdrh ** Return memory as hexadecimal text. 2139c7a60dfSdrh */ 2149c7a60dfSdrh static int test_memget( 2159c7a60dfSdrh void * clientData, 2169c7a60dfSdrh Tcl_Interp *interp, 2179c7a60dfSdrh int objc, 2189c7a60dfSdrh Tcl_Obj *CONST objv[] 2199c7a60dfSdrh ){ 2209c7a60dfSdrh void *p; 2219c7a60dfSdrh int size, n; 2229c7a60dfSdrh char *zBin; 2239c7a60dfSdrh char zHex[100]; 2249c7a60dfSdrh 2259c7a60dfSdrh if( objc!=3 ){ 2269c7a60dfSdrh Tcl_WrongNumArgs(interp, 1, objv, "ADDRESS SIZE"); 2279c7a60dfSdrh return TCL_ERROR; 2289c7a60dfSdrh } 2299c7a60dfSdrh if( textToPointer(Tcl_GetString(objv[1]), &p) ){ 2309c7a60dfSdrh Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0); 2319c7a60dfSdrh return TCL_ERROR; 2329c7a60dfSdrh } 2339c7a60dfSdrh if( Tcl_GetIntFromObj(interp, objv[2], &size) ){ 2349c7a60dfSdrh return TCL_ERROR; 2359c7a60dfSdrh } 2369c7a60dfSdrh if( size<=0 ){ 2379c7a60dfSdrh Tcl_AppendResult(interp, "size must be positive", (char*)0); 2389c7a60dfSdrh return TCL_ERROR; 2399c7a60dfSdrh } 2409c7a60dfSdrh zBin = p; 2419c7a60dfSdrh while( size>0 ){ 2429c7a60dfSdrh if( size>(sizeof(zHex)-1)/2 ){ 2439c7a60dfSdrh n = (sizeof(zHex)-1)/2; 2449c7a60dfSdrh }else{ 2459c7a60dfSdrh n = size; 2469c7a60dfSdrh } 2479c7a60dfSdrh memcpy(zHex, zBin, n); 2489c7a60dfSdrh zBin += n; 2499c7a60dfSdrh size -= n; 2509c7a60dfSdrh sqlite3TestBinToHex(zHex, n); 2519c7a60dfSdrh Tcl_AppendResult(interp, zHex, (char*)0); 2529c7a60dfSdrh } 2539c7a60dfSdrh return TCL_OK; 2549c7a60dfSdrh } 2559c7a60dfSdrh 2569c7a60dfSdrh /* 2572f999a67Sdrh ** Usage: sqlite3_memory_used 2582f999a67Sdrh ** 2592f999a67Sdrh ** Raw test interface for sqlite3_memory_used(). 2602f999a67Sdrh */ 2612f999a67Sdrh static int test_memory_used( 2622f999a67Sdrh void * clientData, 2632f999a67Sdrh Tcl_Interp *interp, 2642f999a67Sdrh int objc, 2652f999a67Sdrh Tcl_Obj *CONST objv[] 2662f999a67Sdrh ){ 2672f999a67Sdrh Tcl_SetObjResult(interp, Tcl_NewWideIntObj(sqlite3_memory_used())); 2682f999a67Sdrh return TCL_OK; 2692f999a67Sdrh } 2702f999a67Sdrh 2712f999a67Sdrh /* 2722f999a67Sdrh ** Usage: sqlite3_memory_highwater ?RESETFLAG? 2732f999a67Sdrh ** 2742f999a67Sdrh ** Raw test interface for sqlite3_memory_highwater(). 2752f999a67Sdrh */ 2762f999a67Sdrh static int test_memory_highwater( 2772f999a67Sdrh void * clientData, 2782f999a67Sdrh Tcl_Interp *interp, 2792f999a67Sdrh int objc, 2802f999a67Sdrh Tcl_Obj *CONST objv[] 2812f999a67Sdrh ){ 2822f999a67Sdrh int resetFlag = 0; 2832f999a67Sdrh if( objc!=1 && objc!=2 ){ 2842f999a67Sdrh Tcl_WrongNumArgs(interp, 1, objv, "?RESET?"); 2852f999a67Sdrh return TCL_ERROR; 2862f999a67Sdrh } 2872f999a67Sdrh if( objc==2 ){ 2882f999a67Sdrh if( Tcl_GetBooleanFromObj(interp, objv[1], &resetFlag) ) return TCL_ERROR; 2892f999a67Sdrh } 2902f999a67Sdrh Tcl_SetObjResult(interp, 2912f999a67Sdrh Tcl_NewWideIntObj(sqlite3_memory_highwater(resetFlag))); 2922f999a67Sdrh return TCL_OK; 2932f999a67Sdrh } 2942f999a67Sdrh 2952f999a67Sdrh /* 2962f999a67Sdrh ** Usage: sqlite3_memdebug_backtrace DEPTH 2972f999a67Sdrh ** 2982f999a67Sdrh ** Set the depth of backtracing. If SQLITE_MEMDEBUG is not defined 2992f999a67Sdrh ** then this routine is a no-op. 3002f999a67Sdrh */ 3012f999a67Sdrh static int test_memdebug_backtrace( 3022f999a67Sdrh void * clientData, 3032f999a67Sdrh Tcl_Interp *interp, 3042f999a67Sdrh int objc, 3052f999a67Sdrh Tcl_Obj *CONST objv[] 3062f999a67Sdrh ){ 3072f999a67Sdrh int depth; 3082f999a67Sdrh if( objc!=2 ){ 3092f999a67Sdrh Tcl_WrongNumArgs(interp, 1, objv, "DEPT"); 3102f999a67Sdrh return TCL_ERROR; 3112f999a67Sdrh } 3122f999a67Sdrh if( Tcl_GetIntFromObj(interp, objv[1], &depth) ) return TCL_ERROR; 3132f999a67Sdrh #ifdef SQLITE_MEMDEBUG 3142f999a67Sdrh { 3152f999a67Sdrh extern void sqlite3_memdebug_backtrace(int); 3162f999a67Sdrh sqlite3_memdebug_backtrace(depth); 3172f999a67Sdrh } 3182f999a67Sdrh #endif 3192f999a67Sdrh return TCL_OK; 3202f999a67Sdrh } 3212f999a67Sdrh 3222f999a67Sdrh /* 3232f999a67Sdrh ** Usage: sqlite3_memdebug_dump FILENAME 3242f999a67Sdrh ** 3252f999a67Sdrh ** Write a summary of unfreed memory to FILENAME. 3262f999a67Sdrh */ 3272f999a67Sdrh static int test_memdebug_dump( 3282f999a67Sdrh void * clientData, 3292f999a67Sdrh Tcl_Interp *interp, 3302f999a67Sdrh int objc, 3312f999a67Sdrh Tcl_Obj *CONST objv[] 3322f999a67Sdrh ){ 3332f999a67Sdrh if( objc!=2 ){ 3342f999a67Sdrh Tcl_WrongNumArgs(interp, 1, objv, "FILENAME"); 3352f999a67Sdrh return TCL_ERROR; 3362f999a67Sdrh } 3379c7a60dfSdrh #if defined(SQLITE_MEMDEBUG) || defined(SQLITE_MEMORY_SIZE) 3382f999a67Sdrh { 3392f999a67Sdrh extern void sqlite3_memdebug_dump(const char*); 3402f999a67Sdrh sqlite3_memdebug_dump(Tcl_GetString(objv[1])); 3412f999a67Sdrh } 3422f999a67Sdrh #endif 3432f999a67Sdrh return TCL_OK; 3442f999a67Sdrh } 3452f999a67Sdrh 3462f999a67Sdrh 3472f999a67Sdrh /* 348a1644fd8Sdanielk1977 ** Usage: sqlite3_memdebug_fail COUNTER ?OPTIONS? 349a1644fd8Sdanielk1977 ** 350a1644fd8Sdanielk1977 ** where options are: 351a1644fd8Sdanielk1977 ** 352*643167ffSdrh ** -repeat <count> 353a1644fd8Sdanielk1977 ** -benigncnt <varname> 3540e6f1546Sdrh ** 3550e6f1546Sdrh ** Arrange for a simulated malloc() failure after COUNTER successes. 356*643167ffSdrh ** If a repeat count is specified, the fault is repeated that many 357*643167ffSdrh ** times. 3580e6f1546Sdrh ** 3590e6f1546Sdrh ** Each call to this routine overrides the prior counter value. 3600e6f1546Sdrh ** This routine returns the number of simulated failures that have 3610e6f1546Sdrh ** happened since the previous call to this routine. 3620e6f1546Sdrh ** 3630e6f1546Sdrh ** To disable simulated failures, use a COUNTER of -1. 3640e6f1546Sdrh */ 3650e6f1546Sdrh static int test_memdebug_fail( 3660e6f1546Sdrh void * clientData, 3670e6f1546Sdrh Tcl_Interp *interp, 3680e6f1546Sdrh int objc, 3690e6f1546Sdrh Tcl_Obj *CONST objv[] 3700e6f1546Sdrh ){ 371a1644fd8Sdanielk1977 int ii; 3720e6f1546Sdrh int iFail; 373*643167ffSdrh int nRepeat = 1; 374a1644fd8Sdanielk1977 Tcl_Obj *pBenignCnt = 0; 375*643167ffSdrh int nBenign; 3760e6f1546Sdrh int nFail = 0; 377a1644fd8Sdanielk1977 378a1644fd8Sdanielk1977 if( objc<2 ){ 379a1644fd8Sdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "COUNTER ?OPTIONS?"); 3800e6f1546Sdrh return TCL_ERROR; 3810e6f1546Sdrh } 3820e6f1546Sdrh if( Tcl_GetIntFromObj(interp, objv[1], &iFail) ) return TCL_ERROR; 383a1644fd8Sdanielk1977 384a1644fd8Sdanielk1977 for(ii=2; ii<objc; ii+=2){ 385a1644fd8Sdanielk1977 int nOption; 386a1644fd8Sdanielk1977 char *zOption = Tcl_GetStringFromObj(objv[ii], &nOption); 387a1644fd8Sdanielk1977 char *zErr = 0; 388a1644fd8Sdanielk1977 389a1644fd8Sdanielk1977 if( nOption>1 && strncmp(zOption, "-repeat", nOption)==0 ){ 390a1644fd8Sdanielk1977 if( ii==(objc-1) ){ 391a1644fd8Sdanielk1977 zErr = "option requires an argument: "; 392ed138fb3Sdrh }else{ 393*643167ffSdrh if( Tcl_GetIntFromObj(interp, objv[ii+1], &nRepeat) ){ 394a1644fd8Sdanielk1977 return TCL_ERROR; 395ed138fb3Sdrh } 396a1644fd8Sdanielk1977 } 397a1644fd8Sdanielk1977 }else if( nOption>1 && strncmp(zOption, "-benigncnt", nOption)==0 ){ 398a1644fd8Sdanielk1977 if( ii==(objc-1) ){ 399a1644fd8Sdanielk1977 zErr = "option requires an argument: "; 400a1644fd8Sdanielk1977 }else{ 401a1644fd8Sdanielk1977 pBenignCnt = objv[ii+1]; 402a1644fd8Sdanielk1977 } 403a1644fd8Sdanielk1977 }else{ 404a1644fd8Sdanielk1977 zErr = "unknown option: "; 405a1644fd8Sdanielk1977 } 406a1644fd8Sdanielk1977 407a1644fd8Sdanielk1977 if( zErr ){ 408a1644fd8Sdanielk1977 Tcl_AppendResult(interp, zErr, zOption, 0); 409a1644fd8Sdanielk1977 return TCL_ERROR; 410a1644fd8Sdanielk1977 } 411a1644fd8Sdanielk1977 } 412a1644fd8Sdanielk1977 413*643167ffSdrh nBenign = sqlite3FaultBenignFailures(SQLITE_FAULTINJECTOR_MALLOC); 414*643167ffSdrh nFail = sqlite3FaultFailures(SQLITE_FAULTINJECTOR_MALLOC); 415*643167ffSdrh sqlite3FaultConfig(SQLITE_FAULTINJECTOR_MALLOC, iFail, nRepeat); 416a1644fd8Sdanielk1977 if( pBenignCnt ){ 417*643167ffSdrh Tcl_ObjSetVar2(interp, pBenignCnt, 0, Tcl_NewIntObj(nBenign), 0); 418a1644fd8Sdanielk1977 } 4190e6f1546Sdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(nFail)); 4200e6f1546Sdrh return TCL_OK; 4210e6f1546Sdrh } 4220e6f1546Sdrh 423cd03724cSdanielk1977 /* 424cd03724cSdanielk1977 ** Usage: sqlite3_memdebug_pending 425cd03724cSdanielk1977 ** 426cd03724cSdanielk1977 ** Return the number of malloc() calls that will succeed before a 427cd03724cSdanielk1977 ** simulated failure occurs. A negative return value indicates that 428cd03724cSdanielk1977 ** no malloc() failure is scheduled. 429cd03724cSdanielk1977 */ 430cd03724cSdanielk1977 static int test_memdebug_pending( 431cd03724cSdanielk1977 void * clientData, 432cd03724cSdanielk1977 Tcl_Interp *interp, 433cd03724cSdanielk1977 int objc, 434cd03724cSdanielk1977 Tcl_Obj *CONST objv[] 435cd03724cSdanielk1977 ){ 436cd03724cSdanielk1977 if( objc!=1 ){ 437cd03724cSdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, ""); 438cd03724cSdanielk1977 return TCL_ERROR; 439cd03724cSdanielk1977 } 440cd03724cSdanielk1977 441cd03724cSdanielk1977 #ifdef SQLITE_MEMDEBUG 442cd03724cSdanielk1977 { 443*643167ffSdrh Tcl_SetObjResult(interp, 444*643167ffSdrh Tcl_NewIntObj(sqlite3FaultPending(SQLITE_FAULTINJECTOR_MALLOC)) 445*643167ffSdrh ); 446cd03724cSdanielk1977 } 447cd03724cSdanielk1977 #endif 448cd03724cSdanielk1977 return TCL_OK; 449cd03724cSdanielk1977 } 450cd03724cSdanielk1977 4510e6f1546Sdrh 4520e6f1546Sdrh /* 4534a50aac5Sdrh ** Usage: sqlite3_memdebug_settitle TITLE 4544a50aac5Sdrh ** 4554a50aac5Sdrh ** Set a title string stored with each allocation. The TITLE is 4564a50aac5Sdrh ** typically the name of the test that was running when the 4574a50aac5Sdrh ** allocation occurred. The TITLE is stored with the allocation 4584a50aac5Sdrh ** and can be used to figure out which tests are leaking memory. 4594a50aac5Sdrh ** 4604a50aac5Sdrh ** Each title overwrite the previous. 4614a50aac5Sdrh */ 4624a50aac5Sdrh static int test_memdebug_settitle( 4634a50aac5Sdrh void * clientData, 4644a50aac5Sdrh Tcl_Interp *interp, 4654a50aac5Sdrh int objc, 4664a50aac5Sdrh Tcl_Obj *CONST objv[] 4674a50aac5Sdrh ){ 4684a50aac5Sdrh const char *zTitle; 4694a50aac5Sdrh if( objc!=2 ){ 4704a50aac5Sdrh Tcl_WrongNumArgs(interp, 1, objv, "TITLE"); 4714a50aac5Sdrh return TCL_ERROR; 4724a50aac5Sdrh } 4734a50aac5Sdrh zTitle = Tcl_GetString(objv[1]); 4744a50aac5Sdrh #ifdef SQLITE_MEMDEBUG 4754a50aac5Sdrh { 4764a50aac5Sdrh extern int sqlite3_memdebug_settitle(const char*); 4774a50aac5Sdrh sqlite3_memdebug_settitle(zTitle); 4784a50aac5Sdrh } 4794a50aac5Sdrh #endif 4804a50aac5Sdrh return TCL_OK; 4814a50aac5Sdrh } 4824a50aac5Sdrh 4834a50aac5Sdrh 4844a50aac5Sdrh /* 4852f999a67Sdrh ** Register commands with the TCL interpreter. 4862f999a67Sdrh */ 4872f999a67Sdrh int Sqlitetest_malloc_Init(Tcl_Interp *interp){ 4882f999a67Sdrh static struct { 4892f999a67Sdrh char *zName; 4902f999a67Sdrh Tcl_ObjCmdProc *xProc; 4912f999a67Sdrh } aObjCmd[] = { 4922f999a67Sdrh { "sqlite3_malloc", test_malloc }, 4932f999a67Sdrh { "sqlite3_realloc", test_realloc }, 4942f999a67Sdrh { "sqlite3_free", test_free }, 4959c7a60dfSdrh { "memset", test_memset }, 4969c7a60dfSdrh { "memget", test_memget }, 4972f999a67Sdrh { "sqlite3_memory_used", test_memory_used }, 4982f999a67Sdrh { "sqlite3_memory_highwater", test_memory_highwater }, 4992f999a67Sdrh { "sqlite3_memdebug_backtrace", test_memdebug_backtrace }, 5002f999a67Sdrh { "sqlite3_memdebug_dump", test_memdebug_dump }, 5010e6f1546Sdrh { "sqlite3_memdebug_fail", test_memdebug_fail }, 502cd03724cSdanielk1977 { "sqlite3_memdebug_pending", test_memdebug_pending }, 5034a50aac5Sdrh { "sqlite3_memdebug_settitle", test_memdebug_settitle }, 5042f999a67Sdrh }; 5052f999a67Sdrh int i; 5062f999a67Sdrh for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ 5072f999a67Sdrh Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0); 5082f999a67Sdrh } 5092f999a67Sdrh return TCL_OK; 5102f999a67Sdrh } 511