mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-30 19:03:16 +03:00
Fix two more memory leaks. (CVS 1603)
FossilOrigin-Name: 98b48704a1ce983677cdb269c24f7bca4ed606f7
This commit is contained in:
19
manifest
19
manifest
@ -1,5 +1,5 @@
|
|||||||
C Documentation\supdates\sand\schanges\sthe\spublish.sh\sscript.\s(CVS\s1602)
|
C Fix\stwo\smore\smemory\sleaks.\s(CVS\s1603)
|
||||||
D 2004-06-16T03:02:01
|
D 2004-06-16T07:45:24
|
||||||
F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
|
F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
|
||||||
F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
|
F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
|
||||||
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
|
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
|
||||||
@ -48,7 +48,7 @@ F src/os_unix.c 8832c78dd95c115b1690054354d90321a791950d
|
|||||||
F src/os_unix.h 1cd6133cf66dea704b8646b70b2dfdcbdd9b3738
|
F src/os_unix.h 1cd6133cf66dea704b8646b70b2dfdcbdd9b3738
|
||||||
F src/os_win.c 337e973ee77797aaab4787e3477a5945fcd97266
|
F src/os_win.c 337e973ee77797aaab4787e3477a5945fcd97266
|
||||||
F src/os_win.h 004eec47b1780fcaf07420ddc2072294b698d48c
|
F src/os_win.h 004eec47b1780fcaf07420ddc2072294b698d48c
|
||||||
F src/pager.c 8e26112df058f73e718938ed07bdbf10ab942c0f
|
F src/pager.c 48356cb434928994ce3c0aac2a6d95e80722c7b3
|
||||||
F src/pager.h bc58d32a9dee464f7268fb68652c130a4216e438
|
F src/pager.h bc58d32a9dee464f7268fb68652c130a4216e438
|
||||||
F src/parse.y 097438674976355a10cf177bd97326c548820b86
|
F src/parse.y 097438674976355a10cf177bd97326c548820b86
|
||||||
F src/pragma.c be8ed53611971f8c93f66cd31129af89e6d58997
|
F src/pragma.c be8ed53611971f8c93f66cd31129af89e6d58997
|
||||||
@ -69,13 +69,13 @@ F src/tokenize.c 183c5d7da11affab5d70d903d33409c8c0ce6c5b
|
|||||||
F src/trigger.c 3ff6f24e5273767117126b712eaae24c3d6466aa
|
F src/trigger.c 3ff6f24e5273767117126b712eaae24c3d6466aa
|
||||||
F src/update.c 6133c876aa126e1771cda165fd992bb0d2f8eb38
|
F src/update.c 6133c876aa126e1771cda165fd992bb0d2f8eb38
|
||||||
F src/utf.c e16737b3fc4201bf7ce9bd8ced5250596aa31b76
|
F src/utf.c e16737b3fc4201bf7ce9bd8ced5250596aa31b76
|
||||||
F src/util.c 90375fa253137562d536ccdd40b297f0fd7413fc
|
F src/util.c 6e93dad9a17b34f37fc270ba871b224240168bf0
|
||||||
F src/vacuum.c f9561c8095407a970af4e6a304b77c4083433d3e
|
F src/vacuum.c f9561c8095407a970af4e6a304b77c4083433d3e
|
||||||
F src/vdbe.c 208705994c0b3b160cb941a5a410838bd5559cf9
|
F src/vdbe.c 208705994c0b3b160cb941a5a410838bd5559cf9
|
||||||
F src/vdbe.h 46f74444a213129bc4b5ce40124dd8ed613b0cde
|
F src/vdbe.h 46f74444a213129bc4b5ce40124dd8ed613b0cde
|
||||||
F src/vdbeInt.h 4e636b1b6c18d1d85b085fe0e5a19d45ad85f382
|
F src/vdbeInt.h 4e636b1b6c18d1d85b085fe0e5a19d45ad85f382
|
||||||
F src/vdbeapi.c ee350b552fc4c1c695b760f914f69e9c5556e829
|
F src/vdbeapi.c ee350b552fc4c1c695b760f914f69e9c5556e829
|
||||||
F src/vdbeaux.c 3476058d13de206cc79cd7015c73e2bb4f37776e
|
F src/vdbeaux.c dc0e7d3bdf3b6f322448b4bee29fe5bec656b4d4
|
||||||
F src/vdbemem.c 1e7df5ed53bc05433c7d3fb28899cf2c82bd16ac
|
F src/vdbemem.c 1e7df5ed53bc05433c7d3fb28899cf2c82bd16ac
|
||||||
F src/where.c 7fee7aeb9278f27324f228c55ab453b5f183b486
|
F src/where.c 7fee7aeb9278f27324f228c55ab453b5f183b486
|
||||||
F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242
|
F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242
|
||||||
@ -177,6 +177,7 @@ F tool/lemon.c db6a3bfaf3388c0f7aea3adb5e05acddcd427016
|
|||||||
F tool/lempar.c 0b5e7a58634e0d448929b8e85f7981c2aa708d57
|
F tool/lempar.c 0b5e7a58634e0d448929b8e85f7981c2aa708d57
|
||||||
F tool/memleak.awk b744b6109566206c746d826f6ecdba34662216bc
|
F tool/memleak.awk b744b6109566206c746d826f6ecdba34662216bc
|
||||||
F tool/memleak2.awk 9cc20c8e8f3c675efac71ea0721ee6874a1566e8
|
F tool/memleak2.awk 9cc20c8e8f3c675efac71ea0721ee6874a1566e8
|
||||||
|
F tool/memleak3.tcl 336eb50b0849dbf99b1d5462d9c37291b01b2b43
|
||||||
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e x
|
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e x
|
||||||
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
|
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
|
||||||
F tool/report1.txt 9eae07f26a8fc53889b45fc833a66a33daa22816
|
F tool/report1.txt 9eae07f26a8fc53889b45fc833a66a33daa22816
|
||||||
@ -223,7 +224,7 @@ F www/support.tcl 1801397edd271cc39a2aadd54e701184b5181248
|
|||||||
F www/tclsqlite.tcl 19191cf2a1010eaeff74c51d83fd5f5a4d899075
|
F www/tclsqlite.tcl 19191cf2a1010eaeff74c51d83fd5f5a4d899075
|
||||||
F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9
|
F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9
|
||||||
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
|
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
|
||||||
P 07b90f3690768e852384fbbde0ba59e69e24d1da
|
P e9a77f8972128550f6ff98dcf854eb7680eaee8b
|
||||||
R 3acf8389b7928b0e6bed5f904140c093
|
R 925b12cad91290c34145812d35712b79
|
||||||
U drh
|
U danielk1977
|
||||||
Z d8b4e54d3b0adc4de12efd128b05998c
|
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
|
** file simultaneously, or one process from reading the database while
|
||||||
** another is writing.
|
** 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 "os.h" /* Must be first to enable large file support */
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
@ -459,6 +459,7 @@ static void pager_reset(Pager *pPager){
|
|||||||
*/
|
*/
|
||||||
static int pager_unwritelock(Pager *pPager){
|
static int pager_unwritelock(Pager *pPager){
|
||||||
PgHdr *pPg;
|
PgHdr *pPg;
|
||||||
|
assert( !pPager->memDb );
|
||||||
if( pPager->state<PAGER_RESERVED ){
|
if( pPager->state<PAGER_RESERVED ){
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
@ -1354,6 +1355,14 @@ int sqlite3pager_close(Pager *pPager){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(pPg=pPager->pAll; pPg; pPg=pNext){
|
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;
|
pNext = pPg->pNextAll;
|
||||||
sqliteFree(pPg);
|
sqliteFree(pPg);
|
||||||
}
|
}
|
||||||
@ -1939,6 +1948,7 @@ int sqlite3pager_unref(void *pData){
|
|||||||
*/
|
*/
|
||||||
static int pager_open_journal(Pager *pPager){
|
static int pager_open_journal(Pager *pPager){
|
||||||
int rc;
|
int rc;
|
||||||
|
assert( !pPager->memDb );
|
||||||
assert( pPager->state>=PAGER_RESERVED );
|
assert( pPager->state>=PAGER_RESERVED );
|
||||||
assert( pPager->journalOpen==0 );
|
assert( pPager->journalOpen==0 );
|
||||||
assert( pPager->useJournal );
|
assert( pPager->useJournal );
|
||||||
@ -2278,6 +2288,8 @@ int sqlite3pager_overwrite(Pager *pPager, Pgno pgno, void *pData){
|
|||||||
void sqlite3pager_dont_write(Pager *pPager, Pgno pgno){
|
void sqlite3pager_dont_write(Pager *pPager, Pgno pgno){
|
||||||
PgHdr *pPg;
|
PgHdr *pPg;
|
||||||
|
|
||||||
|
if( pPager->memDb ) return;
|
||||||
|
|
||||||
pPg = pager_lookup(pPager, pgno);
|
pPg = pager_lookup(pPager, pgno);
|
||||||
pPg->alwaysRollback = 1;
|
pPg->alwaysRollback = 1;
|
||||||
if( pPg && pPg->dirty ){
|
if( pPg && pPg->dirty ){
|
||||||
@ -2374,6 +2386,14 @@ int sqlite3pager_commit(Pager *pPager){
|
|||||||
pPg->pPrevStmt = pPg->pNextStmt = 0;
|
pPg->pPrevStmt = pPg->pNextStmt = 0;
|
||||||
pPg = pPg->pDirty;
|
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->pStmt = 0;
|
||||||
pPager->state = PAGER_SHARED;
|
pPager->state = PAGER_SHARED;
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
@ -2437,7 +2457,13 @@ int sqlite3pager_rollback(Pager *pPager){
|
|||||||
PgHdr *p;
|
PgHdr *p;
|
||||||
for(p=pPager->pAll; p; p=p->pNextAll){
|
for(p=pPager->pAll; p; p=p->pNextAll){
|
||||||
PgHistory *pHist;
|
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);
|
pHist = PGHDR_TO_HIST(p, pPager);
|
||||||
if( pHist->pOrig ){
|
if( pHist->pOrig ){
|
||||||
memcpy(PGHDR_TO_DATA(p), pHist->pOrig, pPager->pageSize);
|
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
|
** This file contains functions for allocating memory, comparing
|
||||||
** strings, and stuff like that.
|
** 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 "sqliteInt.h"
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <ctype.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.
|
** If malloc() ever fails, this global variable gets set to 1.
|
||||||
** This causes the library to abort and never again function.
|
** 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];
|
p = &pi[N_GUARD+1];
|
||||||
memset(p, bZero==0, n);
|
memset(p, bZero==0, n);
|
||||||
#if SQLITE_DEBUG>1
|
#if SQLITE_DEBUG>1
|
||||||
|
print_stack_trace();
|
||||||
fprintf(stderr,"%06d malloc %d bytes at 0x%x from %s:%d\n",
|
fprintf(stderr,"%06d malloc %d bytes at 0x%x from %s:%d\n",
|
||||||
++memcnt, n, (int)p, zFile,line);
|
++memcnt, n, (int)p, zFile,line);
|
||||||
#endif
|
#endif
|
||||||
@ -189,6 +207,7 @@ void *sqlite3Realloc_(void *oldP, int n, char *zFile, int line){
|
|||||||
memset(oldPi, 0xab, (oldK+N_GUARD+2)*sizeof(int));
|
memset(oldPi, 0xab, (oldK+N_GUARD+2)*sizeof(int));
|
||||||
free(oldPi);
|
free(oldPi);
|
||||||
#if SQLITE_DEBUG>1
|
#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",
|
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);
|
++memcnt, oldN, n, (int)oldP, (int)p, zFile, line);
|
||||||
#endif
|
#endif
|
||||||
|
@ -746,9 +746,10 @@ int sqlite3VdbeAggReset(sqlite *db, Agg *pAgg, KeyInfo *pKeyInfo){
|
|||||||
ctx.isError = 0;
|
ctx.isError = 0;
|
||||||
(*pAgg->apFunc[i]->xFinalize)(&ctx);
|
(*pAgg->apFunc[i]->xFinalize)(&ctx);
|
||||||
pMem->z = ctx.pAgg;
|
pMem->z = ctx.pAgg;
|
||||||
if( pMem->z!=0 && pMem->z!=pMem->z ){
|
if( pMem->z!=0 && pMem->z!=pMem->zShort ){
|
||||||
sqliteFree(pMem->z);
|
sqliteFree(pMem->z);
|
||||||
}
|
}
|
||||||
|
sqlite3VdbeMemRelease(&ctx.s);
|
||||||
}else{
|
}else{
|
||||||
sqlite3VdbeMemRelease(pMem);
|
sqlite3VdbeMemRelease(pMem);
|
||||||
}
|
}
|
||||||
|
106
tool/memleak3.tcl
Normal file
106
tool/memleak3.tcl
Normal file
@ -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 ""}
|
||||||
|
}
|
||||||
|
|
Reference in New Issue
Block a user