mirror of https://github.com/sqlite/sqlite
Fix two more memory leaks. (CVS 1603)
FossilOrigin-Name: 98b48704a1ce983677cdb269c24f7bca4ed606f7
This commit is contained in:
parent
7b93ed3d48
commit
eac7a362f6
19
manifest
19
manifest
|
@ -1,5 +1,5 @@
|
|||
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
|
||||
|
@ -48,7 +48,7 @@ F src/os_unix.c 8832c78dd95c115b1690054354d90321a791950d
|
|||
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
|
||||
|
@ -69,13 +69,13 @@ F src/tokenize.c 183c5d7da11affab5d70d903d33409c8c0ce6c5b
|
|||
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
|
||||
|
@ -177,6 +177,7 @@ F tool/lemon.c db6a3bfaf3388c0f7aea3adb5e05acddcd427016
|
|||
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
|
||||
|
@ -223,7 +224,7 @@ F www/support.tcl 1801397edd271cc39a2aadd54e701184b5181248
|
|||
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
|
||||
|
|
|
@ -1 +1 @@
|
|||
e9a77f8972128550f6ff98dcf854eb7680eaee8b
|
||||
98b48704a1ce983677cdb269c24f7bca4ed606f7
|
30
src/pager.c
30
src/pager.c
|
@ -18,7 +18,7 @@
|
|||
** 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"
|
||||
|
@ -459,6 +459,7 @@ static void pager_reset(Pager *pPager){
|
|||
*/
|
||||
static int pager_unwritelock(Pager *pPager){
|
||||
PgHdr *pPg;
|
||||
assert( !pPager->memDb );
|
||||
if( pPager->state<PAGER_RESERVED ){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
@ -1354,6 +1355,14 @@ int sqlite3pager_close(Pager *pPager){
|
|||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
@ -1939,6 +1948,7 @@ int sqlite3pager_unref(void *pData){
|
|||
*/
|
||||
static int pager_open_journal(Pager *pPager){
|
||||
int rc;
|
||||
assert( !pPager->memDb );
|
||||
assert( pPager->state>=PAGER_RESERVED );
|
||||
assert( pPager->journalOpen==0 );
|
||||
assert( pPager->useJournal );
|
||||
|
@ -2278,6 +2288,8 @@ int sqlite3pager_overwrite(Pager *pPager, Pgno pgno, void *pData){
|
|||
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 ){
|
||||
|
@ -2374,6 +2386,14 @@ int sqlite3pager_commit(Pager *pPager){
|
|||
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;
|
||||
|
@ -2437,7 +2457,13 @@ int sqlite3pager_rollback(Pager *pPager){
|
|||
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);
|
||||
|
|
21
src/util.c
21
src/util.c
|
@ -14,12 +14,29 @@
|
|||
** 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.
|
||||
|
@ -82,6 +99,7 @@ void *sqlite3Malloc_(int n, int bZero, char *zFile, int line){
|
|||
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
|
||||
|
@ -189,6 +207,7 @@ void *sqlite3Realloc_(void *oldP, int n, char *zFile, int line){
|
|||
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
|
||||
|
|
|
@ -746,9 +746,10 @@ int sqlite3VdbeAggReset(sqlite *db, Agg *pAgg, KeyInfo *pKeyInfo){
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
#/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 ""}
|
||||
}
|
||||
|
Loading…
Reference in New Issue