remove all memory leaks (CVS 80)
FossilOrigin-Name: bf98cf82a73c54c4eced04994bb1a019844dfc03
This commit is contained in:
parent
aaf88729b7
commit
6e142f5479
29
manifest
29
manifest
@ -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
|
||||
|
@ -1 +1 @@
|
||||
305b043f4f71278d6d2c32e6e457f63efefae20d
|
||||
bf98cf82a73c54c4eced04994bb1a019844dfc03
|
@ -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;
|
||||
}
|
||||
|
28
src/expr.c
28
src/expr.c
@ -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;
|
||||
|
12
src/parse.y
12
src/parse.y
@ -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);}
|
||||
|
@ -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;
|
||||
|
@ -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 *, ...);
|
||||
|
@ -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);
|
||||
|
55
src/util.c
55
src/util.c
@ -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);
|
||||
}
|
||||
|
||||
|
39
src/vdbe.c
39
src/vdbe.c
@ -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:
|
||||
|
@ -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
25
tool/memleak.awk
Normal 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]
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user