-C Documentation\supdates\sand\schanges\sthe\spublish.sh\sscript.\s(CVS\s1602)
-D 2004-06-16T03:02:01
+C Fix\stwo\smore\smemory\sleaks.\s(CVS\s1603)
+D 2004-06-16T07:45:24
F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
F src/os_unix.h 1cd6133cf66dea704b8646b70b2dfdcbdd9b3738
F src/os_win.c 337e973ee77797aaab4787e3477a5945fcd97266
F src/os_win.h 004eec47b1780fcaf07420ddc2072294b698d48c
-F src/pager.c 8e26112df058f73e718938ed07bdbf10ab942c0f
+F src/pager.c 48356cb434928994ce3c0aac2a6d95e80722c7b3
F src/pager.h bc58d32a9dee464f7268fb68652c130a4216e438
F src/parse.y 097438674976355a10cf177bd97326c548820b86
F src/pragma.c be8ed53611971f8c93f66cd31129af89e6d58997
F src/trigger.c 3ff6f24e5273767117126b712eaae24c3d6466aa
F src/update.c 6133c876aa126e1771cda165fd992bb0d2f8eb38
F src/utf.c e16737b3fc4201bf7ce9bd8ced5250596aa31b76
-F src/util.c 90375fa253137562d536ccdd40b297f0fd7413fc
+F src/util.c 6e93dad9a17b34f37fc270ba871b224240168bf0
F src/vacuum.c f9561c8095407a970af4e6a304b77c4083433d3e
F src/vdbe.c 208705994c0b3b160cb941a5a410838bd5559cf9
F src/vdbe.h 46f74444a213129bc4b5ce40124dd8ed613b0cde
F src/vdbeInt.h 4e636b1b6c18d1d85b085fe0e5a19d45ad85f382
F src/vdbeapi.c ee350b552fc4c1c695b760f914f69e9c5556e829
-F src/vdbeaux.c 3476058d13de206cc79cd7015c73e2bb4f37776e
+F src/vdbeaux.c dc0e7d3bdf3b6f322448b4bee29fe5bec656b4d4
F src/vdbemem.c 1e7df5ed53bc05433c7d3fb28899cf2c82bd16ac
F src/where.c 7fee7aeb9278f27324f228c55ab453b5f183b486
F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242
F tool/lempar.c 0b5e7a58634e0d448929b8e85f7981c2aa708d57
F tool/memleak.awk b744b6109566206c746d826f6ecdba34662216bc
F tool/memleak2.awk 9cc20c8e8f3c675efac71ea0721ee6874a1566e8
+F tool/memleak3.tcl 336eb50b0849dbf99b1d5462d9c37291b01b2b43
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e x
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
F tool/report1.txt 9eae07f26a8fc53889b45fc833a66a33daa22816
F www/tclsqlite.tcl 19191cf2a1010eaeff74c51d83fd5f5a4d899075
F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
-P 07b90f3690768e852384fbbde0ba59e69e24d1da
-R 3acf8389b7928b0e6bed5f904140c093
-U drh
-Z d8b4e54d3b0adc4de12efd128b05998c
+P e9a77f8972128550f6ff98dcf854eb7680eaee8b
+R 925b12cad91290c34145812d35712b79
+U danielk1977
+Z 728cd56f54fcbd121f4ed570a3126bce
-e9a77f8972128550f6ff98dcf854eb7680eaee8b
\ No newline at end of file
+98b48704a1ce983677cdb269c24f7bca4ed606f7
\ No newline at end of file
** file simultaneously, or one process from reading the database while
** another is writing.
**
-** @(#) $Id: pager.c,v 1.128 2004/06/15 11:40:09 danielk1977 Exp $
+** @(#) $Id: pager.c,v 1.129 2004/06/16 07:45:24 danielk1977 Exp $
*/
#include "os.h" /* Must be first to enable large file support */
#include "sqliteInt.h"
*/
static int pager_unwritelock(Pager *pPager){
PgHdr *pPg;
+ assert( !pPager->memDb );
if( pPager->state<PAGER_RESERVED ){
return SQLITE_OK;
}
}
}
for(pPg=pPager->pAll; pPg; pPg=pNext){
+#ifndef NDEBUG
+ if( pPager->memDb ){
+ PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
+ assert( !pPg->alwaysRollback );
+ assert( !pHist->pOrig );
+ assert( !pHist->pStmt );
+ }
+#endif
pNext = pPg->pNextAll;
sqliteFree(pPg);
}
*/
static int pager_open_journal(Pager *pPager){
int rc;
+ assert( !pPager->memDb );
assert( pPager->state>=PAGER_RESERVED );
assert( pPager->journalOpen==0 );
assert( pPager->useJournal );
void sqlite3pager_dont_write(Pager *pPager, Pgno pgno){
PgHdr *pPg;
+ if( pPager->memDb ) return;
+
pPg = pager_lookup(pPager, pgno);
pPg->alwaysRollback = 1;
if( pPg && pPg->dirty ){
pPg->pPrevStmt = pPg->pNextStmt = 0;
pPg = pPg->pDirty;
}
+#ifndef NDEBUG
+ for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
+ PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
+ assert( !pPg->alwaysRollback );
+ assert( !pHist->pOrig );
+ assert( !pHist->pStmt );
+ }
+#endif
pPager->pStmt = 0;
pPager->state = PAGER_SHARED;
return SQLITE_OK;
PgHdr *p;
for(p=pPager->pAll; p; p=p->pNextAll){
PgHistory *pHist;
- if( !p->alwaysRollback && !p->dirty ) continue;
+ assert( !p->alwaysRollback );
+ if( !p->dirty ){
+ assert( !((PgHistory *)PGHDR_TO_HIST(p, pPager))->pOrig );
+ assert( !((PgHistory *)PGHDR_TO_HIST(p, pPager))->pStmt );
+ continue;
+ }
+
pHist = PGHDR_TO_HIST(p, pPager);
if( pHist->pOrig ){
memcpy(PGHDR_TO_DATA(p), pHist->pOrig, pPager->pageSize);
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
-** $Id: util.c,v 1.101 2004/06/12 00:42:35 danielk1977 Exp $
+** $Id: util.c,v 1.102 2004/06/16 07:45:29 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <stdarg.h>
#include <ctype.h>
+#if SQLITE_DEBUG>2 && defined(__GLIBC__)
+#include <execinfo.h>
+void print_stack_trace(){
+ void *bt[30];
+ int i;
+ int n = backtrace(bt, 30);
+
+ fprintf(stderr, "STACK: ");
+ for(i=0; i<n;i++){
+ fprintf(stderr, "%p ", bt[i]);
+ }
+ fprintf(stderr, "\n");
+}
+#else
+#define print_stack_trace()
+#endif
+
/*
** If malloc() ever fails, this global variable gets set to 1.
** This causes the library to abort and never again function.
p = &pi[N_GUARD+1];
memset(p, bZero==0, n);
#if SQLITE_DEBUG>1
+ print_stack_trace();
fprintf(stderr,"%06d malloc %d bytes at 0x%x from %s:%d\n",
++memcnt, n, (int)p, zFile,line);
#endif
memset(oldPi, 0xab, (oldK+N_GUARD+2)*sizeof(int));
free(oldPi);
#if SQLITE_DEBUG>1
+ print_stack_trace();
fprintf(stderr,"%06d realloc %d to %d bytes at 0x%x to 0x%x at %s:%d\n",
++memcnt, oldN, n, (int)oldP, (int)p, zFile, line);
#endif
ctx.isError = 0;
(*pAgg->apFunc[i]->xFinalize)(&ctx);
pMem->z = ctx.pAgg;
- if( pMem->z!=0 && pMem->z!=pMem->z ){
+ if( pMem->z!=0 && pMem->z!=pMem->zShort ){
sqliteFree(pMem->z);
}
+ sqlite3VdbeMemRelease(&ctx.s);
}else{
sqlite3VdbeMemRelease(pMem);
}
--- /dev/null
+#/bin/sh
+# \
+exec `which tclsh` $0 "$@"
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+######################################################################
+
+set doco "
+This script is a tool to help track down memory leaks in the sqlite
+library. The library must be compiled with the preprocessor symbol
+SQLITE_DEBUG set to at least 2. It must be set to 3 to enable stack traces.
+
+To use, run the leaky application and save the standard error output.
+Then, execute this program with the first argument the name of the
+application binary (or interpreter) and the second argument the name of the
+text file that contains the collected stderr output.
+
+If all goes well a summary of unfreed allocations is printed out. If the
+GNU C library is in use and SQLITE_DEBUG is 3 or greater a stack trace is
+printed out for each unmatched allocation.
+
+Example:
+
+$ ./testfixture ../sqlite/test/select1.test 2> memtrace.out
+$ tclsh $argv0 ./testfixture memtrace.out
+"
+
+# If stack traces are enabled, the 'addr2line' program is called to
+# translate a binary stack address into a human-readable form.
+set addr2line addr2line
+
+if { [llength $argv]!=2 } {
+ puts "Usage: $argv0 <binary file> <mem trace file>"
+ puts ""
+ puts [string trim $doco]
+ exit -1
+}
+
+
+proc process_input {input_file array_name} {
+ upvar $array_name mem
+ set input [open $input_file]
+
+ set MALLOC {([[:digit:]]+) malloc ([[:digit:]]+) bytes at 0x([[:xdigit:]]+)}
+ set STACK {^STACK: (.*)$}
+ set FREE {[[:digit:]]+ free ([[:digit:]]+) bytes at 0x([[:xdigit:]]+)}
+ set REALLOC {([[:digit:]]+) realloc ([[:digit:]]+) to ([[:digit:]]+)}
+ append REALLOC { bytes at 0x([[:xdigit:]]+) to 0x([[:xdigit:]]+)}
+
+ set stack ""
+ while { ![eof $input] } {
+ set line [gets $input]
+ if {[regexp $STACK $line dummy stack]} {
+ # Do nothing. The variable $stack now stores the hexadecimal stack dump
+ # for the next malloc() or realloc().
+
+ } elseif { [regexp $MALLOC $line dummy mallocid bytes addr] } {
+ # If this is a 'malloc' line, set an entry in the mem array. Each entry
+ # is a list of length three, the number of bytes allocated , the malloc
+ # number and the stack dump when it was allocated.
+ set mem($addr) [list $bytes "malloc $mallocid" $stack]
+ set stack ""
+
+ } elseif { [regexp $FREE $line dummy bytes addr] } {
+ # If this is a 'free' line, remove the entry from the mem array. If the
+ # entry does not exist, or is the wrong number of bytes, announce a
+ # problem. This is more likely a bug in the regular expressions for
+ # this script than an SQLite defect.
+ if { [lindex $mem($addr) 0] != $bytes } {
+ error "byte count mismatch"
+ }
+ unset mem($addr)
+
+ } elseif { [regexp $REALLOC $line dummy mallocid ob b oa a] } {
+ # If it is a realloc line, remove the old mem entry and add a new one.
+ unset mem($oa);
+ set mem($a) [list $b "realloc $mallocid" $stack]
+ set stack ""
+ } else {
+ # puts "REJECT: $line"
+ }
+ }
+
+ close $input
+}
+
+process_input [lindex $argv 1] mem
+set exe [lindex $argv 0]
+
+foreach key [array names mem] {
+ set bytes [lindex $mem($key) 0]
+ set mallocid [lindex $mem($key) 1]
+ set stack [lindex $mem($key) 2]
+ puts "Leaked $bytes bytes at 0x$key: $mallocid"
+ foreach frame [lrange $stack 1 10] {
+ foreach {f l} [split [exec $addr2line -f --exe=$exe $frame] \n] {}
+ puts [format "%-30s %s" $f $l]
+ }
+ if {[llength $stack]>0 } {puts ""}
+}
+