remove all memory leaks (CVS 80)

FossilOrigin-Name: bf98cf82a73c54c4eced04994bb1a019844dfc03
This commit is contained in:
drh 2000-06-08 13:36:40 +00:00
parent aaf88729b7
commit 6e142f5479
12 changed files with 203 additions and 52 deletions

View File

@ -1,28 +1,28 @@
C :-)\s(CVS\s79)
D 2000-06-08T11:25:01
C remove\sall\smemory\sleaks\s(CVS\s80)
D 2000-06-08T13:36:40
F COPYRIGHT 74a8a6531a42e124df07ab5599aad63870fa0bd4
F Makefile.in 17ba1ccf8d2d40c627796bba8f72952365d6d644
F README 51f6a4e7408b34afa5bc1c0485f61b6a4efb6958
F configure 00a5b5c82147a576fa6e82d7c1b0d55c321d6d2c x
F configure.in 6ccfd5fc80517f7cfe605a7fc7e0f62d962a233c
F doc/lemon.html e233a3e97a779c7a87e1bc4528c664a58e49dd47
F src/build.c 5e3b6bab5604cd99019ea6d58f9166d879476991
F src/build.c 925a785da2758269cb8773691e157ea5269178ba
F src/dbbe.c 9b191b16ff01ec5bc0af436558501d07938ba4f0
F src/dbbe.h a8a46f71238e0f09f3ec08fd9d1c8c7f4cdc49bf
F src/delete.c c267b93f7ccb5493b677fa18201880267c699aa8
F src/expr.c ab419c2f09529c8c518484b7f9af68b79e481064
F src/expr.c 8c79de4d19081fe81765dac47bd496c32b606369
F src/insert.c ac4edfff474589c00b2490f206317dc5822122e5
F src/main.c e3297835b8e38ca726ac73f2c2bdb7cf08103197
F src/parse.y bb2126c8313c111184b89af8675911dcb57f1dca
F src/select.c d0b54f5f5a2bb6cd5aebc24c192dea4d4dbaeb84
F src/parse.y e6c61f20620b4a331fecb5217eb556ac41aa441c
F src/select.c b1ffe8e6a03540f690c3749c9c12257fca3463bc
F src/shell.c 3f4afc39a36e4824e8aa262623fd03568874799e
F src/sqlite.h 58da0a8590133777b741f9836beaef3d58f40268
F src/sqliteInt.h 816c491f9896090dde03804fd3f60346456b99df
F src/sqliteInt.h 0aac58ed2e9fe46f24411e2e012fe85cd3457129
F src/tclsqlite.c 9f358618ae803bedf4fb96da5154fd45023bc1f7
F src/tokenize.c 900af9479d0feaa76b0225680196aa81afec930a
F src/tokenize.c cb9eacd12548ee1ae7089eb3177b38851d7f0a1f
F src/update.c d8d90df714bac99c68446a0c49f3d957ca6fc3c8
F src/util.c 33f9baa01e45394ef0cf85361a0e872987884315
F src/vdbe.c 0ce44df13c97472686b376cc93cca5f40079878d
F src/util.c 38e4bb5edf6fa92e677698c45785bf73c69b9e9f
F src/vdbe.c 37f3b0824f90bfe3001dcf337bafb982f9d1b025
F src/vdbe.h 8f79f57c66ce1030f6371ff067b326d627a52c6d
F src/where.c c9b90e7672f4662a83ef9a27a193020d69fe034c
F test/all.test 0950c135cab7e60c07bd745ccfad1476211e5bd7
@ -43,12 +43,13 @@ F test/select5.test b6f8b6bef467764a3edaea4e7cb9b0eb8f02ccd8
F test/sort.test d582086c4bb7df3fbf50aa72e69d7e235e9f8e31
F test/subselect.test bf8b251a92fb091973c1c469ce499dc9648a41d5
F test/table.test 85d6f410d127ec508c6640f02d7c40d218414e81
F test/tester.tcl 44690d463c1dc83a4c76ccde07cc146a988600f6
F test/tester.tcl 95b286791e6256bb6db0165f9342c70fff549a62
F test/update.test 69459302ea75cafac1479e60b0e36efb88123c0e
F test/vacuum.test 8becf5cfeb897108b35cdd996793e7f1df2f28fd
F tool/gdbmdump.c 529e67c78d920606ba196326ea55b57b75fcc82b
F tool/lemon.c 1f0e96515c12e9e413f5b8fdebc79ddcf18ddc9d
F tool/lempar.c a1eec94d6eacc12332368660ec65f3b248853833
F tool/memleak.awk a0a11dd84bf4582acc81c3c61271021ae49b3f15
F tool/opNames.awk 2bd9071a138e4e2be13dc98fe066398a61219e1e
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
F tool/renumberOps.awk 6d067177ad5f8d711b79577b462da9b3634bd0a9
@ -56,7 +57,7 @@ F www/c_interface.tcl 9ac800854272db5fe439e07b7435b243a5422293
F www/changes.tcl 04e66b4257589ff78a7e1de93e9dda4725fb03d6
F www/index.tcl 52e29a4eeda8d59e91af43c61fef177c5f2ffd53
F www/sqlite.tcl 2f933ce18cffd34a0a020a82435ab937137970fd
P 923c14fe120c7d5470a18257659154c4f98226b7
R 57bfb2e9c02ed1359339dbb2f56b538b
P 305b043f4f71278d6d2c32e6e457f63efefae20d
R 2e8cf1a074c330c6453a374880c3eab1
U drh
Z d5e2038c5fa3d3fb8e65d77ade627b18
Z f0a43ffe3166fea312bf9330021c453e

View File

@ -1 +1 @@
305b043f4f71278d6d2c32e6e457f63efefae20d
bf98cf82a73c54c4eced04994bb1a019844dfc03

View File

@ -33,7 +33,7 @@
** COPY
** VACUUM
**
** $Id: build.c,v 1.16 2000/06/07 23:51:50 drh Exp $
** $Id: build.c,v 1.17 2000/06/08 13:36:40 drh Exp $
*/
#include "sqliteInt.h"
@ -191,6 +191,7 @@ void sqliteDeleteTable(sqlite *db, Table *pTable){
pNext = pIndex->pNext;
sqliteDeleteIndex(db, pIndex);
}
sqliteFree(pTable->zName);
sqliteFree(pTable->aCol);
sqliteFree(pTable);
}
@ -202,8 +203,7 @@ void sqliteDeleteTable(sqlite *db, Table *pTable){
** be freed by the calling function.
*/
char *sqliteTableNameFromToken(Token *pName){
char *zName = 0;
sqliteSetNString(&zName, pName->z, pName->n, 0);
char *zName = sqliteStrNDup(pName->z, pName->n);
sqliteDequote(zName);
return zName;
}

View File

@ -23,7 +23,7 @@
*************************************************************************
** This file contains C code routines used for processing expressions
**
** $Id: expr.c,v 1.12 2000/06/08 11:25:01 drh Exp $
** $Id: expr.c,v 1.13 2000/06/08 13:36:40 drh Exp $
*/
#include "sqliteInt.h"
@ -118,8 +118,7 @@ int sqliteExprResolveIds(Parse *pParse, IdList *pTabList, Expr *pExpr){
case TK_ID: {
int cnt = 0; /* Number of matches */
int i; /* Loop counter */
char *z = 0;
sqliteSetNString(&z, pExpr->token.z, pExpr->token.n, 0);
char *z = sqliteStrNDup(pExpr->token.z, pExpr->token.n);
for(i=0; i<pTabList->nId; i++){
int j;
Table *pTab = pTabList->a[i].pTab;
@ -159,10 +158,8 @@ int sqliteExprResolveIds(Parse *pParse, IdList *pTabList, Expr *pExpr){
pRight = pExpr->pRight;
assert( pLeft && pLeft->op==TK_ID );
assert( pRight && pRight->op==TK_ID );
zLeft = 0;
sqliteSetNString(&zLeft, pLeft->token.z, pLeft->token.n, 0);
zRight = 0;
sqliteSetNString(&zRight, pRight->token.z, pRight->token.n, 0);
zLeft = sqliteStrNDup(pLeft->token.z, pLeft->token.n);
zRight = sqliteStrNDup(pRight->token.z, pRight->token.n);
for(i=0; i<pTabList->nId; i++){
int j;
char *zTab;
@ -512,8 +509,23 @@ void sqliteExprCode(Parse *pParse, Expr *pExpr){
sqliteVdbeAddOp(v, OP_AddImm, -1, 0, 0, 0);
break;
}
case TK_NOT:
case TK_UMINUS: {
assert( pExpr->pLeft );
if( pExpr->pLeft->op==TK_INTEGER ){
int i = atoi(pExpr->pLeft->token.z);
sqliteVdbeAddOp(v, OP_Integer, -i, 0, 0, 0);
break;
}else if( pExpr->pLeft->op==TK_FLOAT ){
Token *p = &pExpr->pLeft->token;
char *z = sqliteMalloc( p->n + 2 );
sprintf(z, "-%.*s", p->n, p->z);
sqliteVdbeAddOp(v, OP_String, 0, 0, z, 0);
sqliteFree(z);
break;
}
/* Fall true into TK_NOT */
}
case TK_NOT: {
sqliteExprCode(pParse, pExpr->pLeft);
sqliteVdbeAddOp(v, op, 0, 0, 0, 0);
break;

View File

@ -26,7 +26,7 @@
** the parser. Lemon will also generate a header file containing
** numeric codes for all of the tokens.
**
** @(#) $Id: parse.y,v 1.16 2000/06/07 23:51:50 drh Exp $
** @(#) $Id: parse.y,v 1.17 2000/06/08 13:36:40 drh Exp $
*/
%token_prefix TK_
%token_type {Token}
@ -271,16 +271,14 @@ itemlist(A) ::= item(X). {A = sqliteExprListAppend(0,X,0);}
item(A) ::= INTEGER(X). {A = sqliteExpr(TK_INTEGER, 0, 0, &X);}
item(A) ::= PLUS INTEGER(X). {A = sqliteExpr(TK_INTEGER, 0, 0, &X);}
item(A) ::= MINUS INTEGER(X). {
A = sqliteExpr(TK_INTEGER, 0, 0, 0);
A->token.z = 0;
sqliteSetNString(&A->token.z, "-", 1, X.z, X.n, 0);
A = sqliteExpr(TK_UMINUS, 0, 0, 0);
A->pLeft = sqliteExpr(TK_INTEGER, 0, 0, &X);
}
item(A) ::= FLOAT(X). {A = sqliteExpr(TK_FLOAT, 0, 0, &X);}
item(A) ::= PLUS FLOAT(X). {A = sqliteExpr(TK_FLOAT, 0, 0, &X);}
item(A) ::= MINUS FLOAT(X). {
A = sqliteExpr(TK_FLOAT, 0, 0, 0);
A->token.z = 0;
sqliteSetNString(&A->token.z, "-", 1, X.z, X.n, 0);
A = sqliteExpr(TK_UMINUS, 0, 0, 0);
A->pLeft = sqliteExpr(TK_FLOAT, 0, 0, &X);
}
item(A) ::= STRING(X). {A = sqliteExpr(TK_STRING, 0, 0, &X);}
item(A) ::= NULL. {A = sqliteExpr(TK_NULL, 0, 0, 0);}

View File

@ -24,7 +24,7 @@
** This file contains C code routines that are called by the parser
** to handle SELECT statements.
**
** $Id: select.c,v 1.21 2000/06/08 11:25:01 drh Exp $
** $Id: select.c,v 1.22 2000/06/08 13:36:40 drh Exp $
*/
#include "sqliteInt.h"
@ -144,6 +144,7 @@ static int selectInnerLoop(
}
zSortOrder[pOrderBy->nExpr] = 0;
sqliteVdbeAddOp(v, OP_SortMakeKey, pOrderBy->nExpr, 0, zSortOrder, 0);
sqliteFree(zSortOrder);
sqliteVdbeAddOp(v, OP_SortPut, 0, 0, 0, 0);
}else
@ -378,12 +379,12 @@ static int matchOrderbyToColumn(
for(j=0; j<pEList->nExpr; j++){
if( pEList->a[i].zName && (pE->op==TK_ID || pE->op==TK_STRING) ){
char *zName = pEList->a[i].zName;
char *zLabel = 0;
sqliteSetNString(&zLabel, pE->token.z, pE->token.n, 0);
char *zLabel = sqliteStrNDup(pE->token.z, pE->token.n);
sqliteDequote(zLabel);
if( sqliteStrICmp(zName, zLabel)==0 ){
match = 1;
}
sqliteFree(zLabel);
}
if( match==0 && sqliteExprCompare(pE, pEList->a[i].pExpr) ){
match = 1;

View File

@ -23,7 +23,7 @@
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.22 2000/06/07 23:51:51 drh Exp $
** @(#) $Id: sqliteInt.h,v 1.23 2000/06/08 13:36:40 drh Exp $
*/
#include "sqlite.h"
#include "dbbe.h"
@ -40,11 +40,23 @@
# define sqliteMalloc(X) sqliteMalloc_(X,__FILE__,__LINE__)
# define sqliteFree(X) sqliteFree_(X,__FILE__,__LINE__)
# define sqliteRealloc(X,Y) sqliteRealloc_(X,Y,__FILE__,__LINE__)
# define sqliteStrDup(X) sqliteStrDup_(X,__FILE__,__LINE__)
# define sqliteStrNDup(X,Y) sqliteStrNDup_(X,Y,__FILE__,__LINE__)
void sqliteStrRealloc(char**);
#else
# define sqliteStrRealloc(X)
#endif
/*
** The following global variables are used for testing and debugging
** only. Thy only work if MEMORY_DEBUG is defined.
*/
#ifdef MEMORY_DEBUG
int sqlite_nMalloc; /* Number of sqliteMalloc() calls */
int sqlite_nFree; /* Number of sqliteFree() calls */
int sqlite_iMallocFail; /* Fail sqliteMalloc() after this many calls */
#endif
/*
** The number of entries in the in-memory hash table holding the
** schema.
@ -306,10 +318,14 @@ int sqliteSortCompare(const char *, const char *);
void *sqliteMalloc_(int,char*,int);
void sqliteFree_(void*,char*,int);
void *sqliteRealloc_(void*,int,char*,int);
char *sqliteStrDup_(const char*,char*,int);
char *sqliteStrNDup_(const char*, int,char*,int);
#else
void *sqliteMalloc(int);
void sqliteFree(void*);
void *sqliteRealloc(void*,int);
char *sqliteStrDup(const char*);
char *sqliteStrNDup(const char*, int);
#endif
int sqliteGetToken(const char*, int *);
void sqliteSetString(char **, const char *, ...);

View File

@ -27,7 +27,7 @@
** individual tokens and sends those tokens one-by-one over to the
** parser for analysis.
**
** $Id: tokenize.c,v 1.9 2000/06/07 02:04:23 drh Exp $
** $Id: tokenize.c,v 1.10 2000/06/08 13:36:40 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@ -328,6 +328,7 @@ int sqliteRunParser(Parse *pParse, char *zSql, char **pzErrMsg){
** special SQL comments. Check for the special comments
** here and take approriate action if found.
*/
#ifndef NDEBUG
char *z = pParse->sLastToken.z;
if( sqliteStrNICmp(z,"--parser-trace-on--",19)==0 ){
trace = stderr;
@ -339,7 +340,26 @@ int sqliteRunParser(Parse *pParse, char *zSql, char **pzErrMsg){
pParse->db->flags |= SQLITE_VdbeTrace;
}else if( sqliteStrNICmp(z,"--vdbe-trace-off--", 18)==0 ){
pParse->db->flags &= ~SQLITE_VdbeTrace;
#ifdef MEMORY_DEBUG
}else if( sqliteStrNICmp(z,"--malloc-file=",14)==0 ){
sqlite_iMallocFail = atoi(&z[14]);
}else if( sqliteStrNICmp(z,"--malloc-stats--", 16)==0 ){
if( pParse->xCallback ){
static char *azName[4] = {"malloc", "free", "to_fail", 0 };
char *azArg[4];
char zVal[3][30];
sprintf(zVal[0],"%d", sqlite_nMalloc);
sprintf(zVal[1],"%d", sqlite_nFree);
sprintf(zVal[2],"%d", sqlite_iMallocFail);
azArg[0] = zVal[0];
azArg[1] = zVal[1];
azArg[2] = zVal[2];
azArg[3] = 0;
pParse->xCallback(pParse->pArg, 3, azArg, azName);
}
#endif
}
#endif
break;
}
case TK_ILLEGAL:
@ -349,31 +369,36 @@ int sqliteRunParser(Parse *pParse, char *zSql, char **pzErrMsg){
break;
default:
sqliteParser(pEngine, tokenType, pParse->sLastToken, pParse);
if( pParse->zErrMsg ){
if( pParse->zErrMsg && pParse->sErrToken.z ){
sqliteSetNString(pzErrMsg, "near \"", -1,
pParse->sErrToken.z, pParse->sErrToken.n,
"\": ", -1,
pParse->zErrMsg, -1,
0);
nErr++;
sqliteFree(pParse->zErrMsg);
pParse->zErrMsg = 0;
}
break;
}
}
if( nErr==0 ){
sqliteParser(pEngine, 0, pParse->sLastToken, pParse);
if( pParse->zErrMsg ){
if( pParse->zErrMsg && pParse->sErrToken.z ){
sqliteSetNString(pzErrMsg, "near \"", -1,
pParse->sErrToken.z, pParse->sErrToken.n,
"\": ", -1,
pParse->zErrMsg, -1,
0);
nErr++;
sqliteFree(pParse->zErrMsg);
pParse->zErrMsg = 0;
}
}
sqliteParserFree(pEngine, free);
if( pParse->zErrMsg ){
if( pzErrMsg ){
sqliteFree(*pzErrMsg);
*pzErrMsg = pParse->zErrMsg;
}else{
sqliteFree(pParse->zErrMsg);

View File

@ -26,7 +26,7 @@
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
** $Id: util.c,v 1.11 2000/06/05 16:01:39 drh Exp $
** $Id: util.c,v 1.12 2000/06/08 13:36:41 drh Exp $
*/
#include "sqliteInt.h"
#include <stdarg.h>
@ -43,6 +43,11 @@ void *sqliteMalloc_(int n, char *zFile, int line){
void *p;
int *pi;
int k;
sqlite_nMalloc++;
if( sqlite_iMallocFail>=0 ){
sqlite_iMallocFail--;
if( sqlite_iMallocFail==0 ) return 0;
}
k = (n+sizeof(int)-1)/sizeof(int);
pi = malloc( (3+k)*sizeof(int));
if( pi==0 ) return 0;
@ -65,6 +70,7 @@ void sqliteFree_(void *p, char *zFile, int line){
int *pi, k, n;
pi = p;
pi -= 2;
sqlite_nFree++;
if( pi[0]!=0xdead1122 ){
fprintf(stderr,"Low-end memory corruption at 0x%x\n", (int)p);
return;
@ -123,7 +129,7 @@ void *sqliteRealloc_(void *oldP, int n, char *zFile, int line){
memset(oldPi, 0, (oldK+3)*sizeof(int));
free(oldPi);
#if MEMORY_DEBUG>1
fprintf(stderr,"realloc %d->%d bytes at 0x%x->0x%x at %s:%d\n", oldN, n,
fprintf(stderr,"realloc %d to %d bytes at 0x%x to 0x%x at %s:%d\n", oldN, n,
(int)oldP, (int)p, zFile, line);
#endif
return p;
@ -142,6 +148,24 @@ void sqliteStrRealloc(char **pz){
*pz = zNew;
}
/*
** Make a copy of a string in memory obtained from sqliteMalloc()
*/
char *sqliteStrDup_(const char *z, char *zFile, int line){
char *zNew = sqliteMalloc_(strlen(z)+1, zFile, line);
if( zNew ) strcpy(zNew, z);
return zNew;
}
char *sqliteStrNDup_(const char *z, int n, char *zFile, int line){
char *zNew = sqliteMalloc_(n+1, zFile, line);
if( zNew ){
memcpy(zNew, z, n);
zNew[n] = 0;
}
return zNew;
}
#else /* !defined(MEMORY_DEBUG) */
/*
** Allocate new memory and set it to zero. Return NULL if
@ -178,6 +202,23 @@ void *sqliteRealloc(void *p, int n){
}
return realloc(p, n);
}
/*
** Make a copy of a string in memory obtained from sqliteMalloc()
*/
char *sqliteStrDup(const char *z){
char *zNew = sqliteMalloc(strlen(z)+1);
if( zNew ) strcpy(zNew, z);
return zNew;
}
char *sqliteStrNDup(const char *z, int n){
char *zNew = sqliteMalloc(n+1);
if( zNew ){
memcpy(zNew, z, n);
zNew[n] = 0;
}
return zNew;
}
#endif /* MEMORY_DEBUG */
/*
@ -210,6 +251,11 @@ void sqliteSetString(char **pz, const char *zFirst, ...){
zResult += strlen(zResult);
}
va_end(ap);
#ifdef MEMORY_DEBUG
#if MEMORY_DEBUG>1
fprintf(stderr,"string at 0x%x is %s\n", (int)*pz, *pz);
#endif
#endif
}
/*
@ -243,6 +289,11 @@ void sqliteSetNString(char **pz, ...){
zResult += n;
}
*zResult = 0;
#ifdef MEMORY_DEBUG
#if MEMORY_DEBUG>1
fprintf(stderr,"string at 0x%x is %s\n", (int)*pz, *pz);
#endif
#endif
va_end(ap);
}

View File

@ -41,7 +41,7 @@
** But other routines are also provided to help in building up
** a program instruction by instruction.
**
** $Id: vdbe.c,v 1.27 2000/06/07 15:39:04 drh Exp $
** $Id: vdbe.c,v 1.28 2000/06/08 13:36:41 drh Exp $
*/
#include "sqliteInt.h"
#include <unistd.h>
@ -254,7 +254,7 @@ int sqliteVdbeAddOp(Vdbe *p, int op, int p1, int p2, const char *p3, int lbl){
}
p->aOp[i].p2 = p2;
if( p3 && p3[0] ){
sqliteSetString(&p->aOp[i].p3, p3, 0);
p->aOp[i].p3 = sqliteStrDup(p3);
}else{
p->aOp[i].p3 = 0;
}
@ -523,8 +523,7 @@ static int hardStringify(Vdbe *p, int i){
p->aStack[i].flags |= STK_Str;
return 0;
}
p->zStack[i] = 0;
sqliteSetString(&p->zStack[i], zBuf, 0);
p->zStack[i] = sqliteStrDup(zBuf);
if( p->zStack[i]==0 ) return 1;
p->aStack[i].n = strlen(p->zStack[i])+1;
p->aStack[i].flags |= STK_Str|STK_Dyn;
@ -846,7 +845,6 @@ static Sorter *Merge(Sorter *pLeft, Sorter *pRight){
return sHead.pNext;
}
/*
** Execute the program in the VDBE.
**
@ -886,11 +884,17 @@ int sqliteVdbeExec(
/* if( pzErrMsg ){ *pzErrMsg = 0; } */
for(pc=0; rc==SQLITE_OK && pc<p->nOp && pc>=0; pc++){
pOp = &p->aOp[pc];
/* Only allow tracing if NDEBUG is not defined.
*/
#ifndef NDEBUG
if( p->trace ){
fprintf(p->trace,"%4d %-12s %4d %4d %s\n",
pc, zOpName[pOp->opcode], pOp->p1, pOp->p2,
pOp->p3 ? pOp->p3 : "");
}
#endif
switch( pOp->opcode ){
/* Opcode: Goto P2 * *
**
@ -1893,7 +1897,6 @@ int sqliteVdbeExec(
*/
case OP_KeyAsData: {
int i = pOp->p1;
VdbeTable *pTab;
if( i>=0 && i<p->nTable && p->aTab[i].pTable!=0 ){
p->aTab[i].keyAsData = pOp->p2;
}
@ -2683,6 +2686,7 @@ int sqliteVdbeExec(
int i = pOp->p1;
int tos = p->tos;
Mem *pMem;
char *zOld;
if( tos<0 ) goto not_enough_stack;
if( i>=p->nMem ){
int nOld = p->nMem;
@ -2695,14 +2699,16 @@ int sqliteVdbeExec(
}
pMem = &p->aMem[i];
if( pMem->s.flags & STK_Dyn ){
sqliteFree(pMem->z);
zOld = pMem->z;
}else{
zOld = 0;
}
pMem->s = p->aStack[tos];
if( pMem->s.flags & STK_Str ){
pMem->z = 0;
sqliteSetString(&pMem->z, p->zStack[tos], 0);
pMem->z = sqliteStrNDup(p->zStack[tos], pMem->s.n);
pMem->s.flags |= STK_Dyn;
}
if( zOld ) sqliteFree(zOld);
PopStack(p, 1);
break;
}
@ -2824,6 +2830,12 @@ int sqliteVdbeExec(
if( pFocus==0 ) goto no_mem;
if( i>=0 && i<p->agg.nMem ){
Mem *pMem = &pFocus->aMem[i];
char *zOld;
if( pMem->s.flags & STK_Dyn ){
zOld = pMem->z;
}else{
zOld = 0;
}
pMem->s = p->aStack[tos];
if( pMem->s.flags & STK_Str ){
pMem->z = sqliteMalloc( p->aStack[tos].n );
@ -2831,6 +2843,7 @@ int sqliteVdbeExec(
memcpy(pMem->z, p->zStack[tos], pMem->s.n);
pMem->s.flags |= STK_Str|STK_Dyn;
}
if( zOld ) sqliteFree(zOld);
}
PopStack(p, 1);
break;
@ -2973,6 +2986,13 @@ int sqliteVdbeExec(
break;
}
}
/* The following code adds nothing to the actual functionality
** of the program. It is only here for testing and debugging.
** On the other hand, it does burn CPU cycles every time through
** the evaluator loop. So we can leave it out when NDEBUG is defined.
*/
#ifndef NDEBUG
if( pc<-1 || pc>=p->nOp ){
sqliteSetString(pzErrMsg, "jump destination out of range", 0);
rc = SQLITE_INTERNAL;
@ -2999,6 +3019,7 @@ int sqliteVdbeExec(
}
fprintf(p->trace,"\n");
}
#endif
}
cleanup:

View File

@ -23,7 +23,7 @@
# This file implements some common TCL routines used for regression
# testing the SQLite library
#
# $Id: tester.tcl,v 1.4 2000/05/31 17:59:27 drh Exp $
# $Id: tester.tcl,v 1.5 2000/06/08 13:36:41 drh Exp $
# Create a test database
#
@ -74,6 +74,7 @@ proc do_test {name cmd expected} {
#
proc finish_test {} {
global nTest nErr
catch {db close}
puts "$nErr errors out of $nTest tests"
exit $nErr
}

25
tool/memleak.awk Normal file
View File

@ -0,0 +1,25 @@
#
# This script looks for memory leaks by analyzing the output of "sqlite"
# when compiled with the MEMORY_DEBUG=2 option.
#
/^malloc / {
mem[$5] = $0
}
/^realloc / {
mem[$7] = "";
mem[$9] = $0
}
/^free / {
mem[$5] = "";
}
/^string at / {
addr = $3
sub("string at " addr " is ","")
str[addr] = $0
}
END {
for(addr in mem){
if( mem[addr]=="" ) continue
print mem[addr], str[addr]
}
}