-C In\sthe\ssqlite3_limit()\sinterface,\stake\sout\sthe\sfeature\swhere\szero\smeans\nuse\sthe\shard\supper\sbound.\s\sIf\san\sapplication\swants\sthe\shard\supper\sbound,\nit\scan\sset\sthe\slimit\sto\s0x7fffffff\sand\sthe\sbound\swill\sbe\sautomatically\ntruncated.\s(CVS\s4900)
-D 2008-03-20T18:00:49
+C Add\ssome\smore\slogging\sto\sthe\smalloc\ssystem\sused\swhen\sSQLITE_MEMDEBUG\sis\sdefined.\s(CVS\s4901)
+D 2008-03-21T14:22:44
F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
F Makefile.in cf434ce8ca902e69126ae0f94fc9f7dc7428a5fa
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
F src/malloc.c 60e392a4c12c839517f9b0db7b995f825444fb35
F src/md5.c c5fdfa5c2593eaee2e32a5ce6c6927c986eaf217
F src/mem1.c fc716ff521b6dd3e43eaa211967383308800e70a
-F src/mem2.c a17fd71f39e593f46445282c36077231e70a31eb
+F src/mem2.c a4694eff7397de20a7e4b3d70c3faeaf63bf4647
F src/mem3.c 52547678a2ae50c203d54be1a5bf51eb02438a3f
F src/mem4.c 45c328ec6dcb7e8d319cb383615b5fe547ca5409
F src/mem5.c 11d98b76f77873aab86b543cbd1a8ddc4e680d58
F src/test_func.c 9e9b33ff083b65da91c389cece903bc32de06f01
F src/test_hexio.c 1a1cd8324d57585ea86b922f609fa1fbaaf9662d
F src/test_loadext.c 22065d601a18878e5542191001f0eaa5d77c0ed8
-F src/test_malloc.c bba50714c0aa75552bc535473afb8213f18c2fe6
+F src/test_malloc.c 52d8d7003c0b2183fd67de45c8b64ee7eb2656ea
F src/test_md5.c bca40b727c57462ddb415e57c5323445a1bb1a40
F src/test_onefile.c 2fea6d22f13f5f286356c80c77ffd41f995f2b7a
F src/test_schema.c 12c9de7661d6294eec2d57afbb52e2af1128084f
F test/tableapi.test 791f7e3891d9b70bdb43b311694bf5e9befcbc34
F test/tclsqlite.test 3fac87cb1059c46b8fa8a60b553f4f1adb0fb6d9
F test/temptable.test 19b851b9e3e64d91e9867619b2a3f5fffee6e125
-F test/tester.tcl c32f6dfadf9148482d533236c4efee972791d424
+F test/tester.tcl 482f1b003f937249d3b3d6cc9aacd540c9b50635
F test/thread001.test 8fbd9559da0bbdc273e00318c7fd66c162020af7
F test/thread002.test 2c4ad2c386f60f6fe268cd91c769ee35b3c1fd0b
F test/thread1.test 776c9e459b75ba905193b351926ac4019b049f35
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
-P 4c4be4c3c8aae97f1d85442b25afba9f0b02c8b3
-R 10f06e62355868edd7f0d48570d09623
-U drh
-Z 5ee7e525e24d3023d636da94fdb9521e
+P d6be1f495ec57158f7bcca3e32145a9a8fde723a
+R 28cbaee3047482f301b44be906e76f05
+U danielk1977
+Z a16e4b15bf7acabffb6c1a202fc0f688
-d6be1f495ec57158f7bcca3e32145a9a8fde723a
\ No newline at end of file
+79738f582fbac87f2d335e0c6b7f53e3054b41ba
\ No newline at end of file
** This file contains the C functions that implement a memory
** allocation subsystem for use by SQLite.
**
-** $Id: mem2.c,v 1.22 2008/02/19 15:15:16 drh Exp $
+** $Id: mem2.c,v 1.23 2008/03/21 14:22:44 danielk1977 Exp $
*/
#include "sqliteInt.h"
** The number of levels of backtrace to save in new allocations.
*/
int nBacktrace;
+ void (*xBacktrace)(int, int, void **);
/*
** Title text to insert in front of each block
void *aAddr[40];
pHdr->nBacktrace = backtrace(aAddr, mem.nBacktrace+1)-1;
memcpy(pBt, &aAddr[1], pHdr->nBacktrace*sizeof(void*));
+ if( mem.xBacktrace ){
+ mem.xBacktrace(nByte, pHdr->nBacktrace-1, &aAddr[1]);
+ }
}else{
pHdr->nBacktrace = 0;
}
mem.nBacktrace = depth;
}
+void sqlite3MemdebugBacktraceCallback(void (*xBacktrace)(int, int, void **)){
+ mem.xBacktrace = xBacktrace;
+}
+
/*
** Set the title string for subsequent allocations.
*/
** 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"
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.
{ "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++){
# This file implements some common TCL routines used for regression
# testing the SQLite library
#
-# $Id: tester.tcl,v 1.107 2008/03/19 16:08:54 drh Exp $
+# $Id: tester.tcl,v 1.108 2008/03/21 14:22:44 danielk1977 Exp $
set tcl_precision 15
return [md5 $txt]
}
+proc memdebug_log_sql {database} {
+ set data [sqlite3_memdebug_log dump]
+ set nFrame [expr [llength [lindex $data 0]]-2]
+ if {$nFrame < 0} { return "" }
+
+ set tbl "CREATE TABLE ${database}.malloc(nCall, nByte"
+ for {set ii 1} {$ii <= $nFrame} {incr ii} {
+ append tbl ", f${ii}"
+ }
+ append tbl ");\n"
+
+ set sql ""
+ foreach e $data {
+ append sql "INSERT INTO ${database}.malloc VALUES([join $e ,]);\n"
+ foreach f [lrange $e 2 end] {
+ set frames($f) 1
+ }
+ }
+
+ set tbl2 "CREATE TABLE ${database}.frame(frame INTEGER PRIMARY KEY, line);\n"
+
+ foreach f [array names frames] {
+ set addr [format %x $f]
+ set cmd "addr2line -e [info nameofexec] $addr"
+ set line [eval exec $cmd]
+ append sql "INSERT INTO ${database}.frame VALUES($f, '$line');\n"
+ }
+
+ return "BEGIN; ${tbl}${tbl2}${sql} ; COMMIT;"
+}
+proc memdebug_log_pp2 {db iLevel iParentFrame iDepth} {
+ set extra 1
+ if {$iParentFrame != 0} {
+ set extra "f[expr $iLevel-1] = $iParentFrame"
+ }
+ set leader [string repeat " " [expr $iLevel -1]]
+ $db eval "
+ select
+ sum(ncall) calls,
+ sum(nbyte) as bytes,
+ frame,
+ line FROM malloc,
+ frame WHERE f${iLevel}=frame AND $extra
+ GROUP BY f${iLevel} ORDER BY calls DESC
+ " {
+ puts [format "%s%-10s %10s %s" $leader $calls $bytes $line]
+ if {$iLevel < $iDepth} {
+ memdebug_log_pp2 $db [expr $iLevel + 1] $frame $iDepth
+ }
+ }
+}
+proc memdebug_log_strip {db} {
+ set nFrame [expr [llength [$db eval "SELECT * FROM malloc LIMIT 1"]] - 2]
+
+ set update "UPDATE malloc SET "
+ for {set ii 1} {$ii <= $nFrame} {incr ii} {
+ if {$ii == $nFrame} {
+ append update "f${ii} = 0"
+ } else {
+ append update "f${ii} = f[expr $ii+1], "
+ }
+ }
+ append update "
+ WHERE
+ (SELECT line FROM frame WHERE frame = f1) LIKE '%malloc.c:%' OR
+ (SELECT line FROM frame WHERE frame = f1) LIKE '%mem2.c:%'
+ "
+
+ $db eval $update
+ $db eval $update
+ $db eval $update
+}
+proc memdebug_log_pp {{iDepth 1}} {
+ set sql [memdebug_log_sql main]
+ if {$sql eq ""} return
+
+ sqlite3 mddb :memory:
+ mddb eval $sql
+ memdebug_log_strip mddb
+
+ memdebug_log_pp2 mddb 1 0 $iDepth
+ mddb close
+}
# Copy file $from into $to. This is used because some versions of
# TCL for windows (notably the 8.4.1 binary package shipped with the