Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | remove all memory leaks (CVS 80) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
bf98cf82a73c54c4eced04994bb1a019 |
User & Date: | drh 2000-06-08 13:36:40.000 |
Context
2000-06-08
| ||
15:10 | :-) (CVS 81) (check-in: 61c381e7e6 user: drh tags: trunk) | |
13:36 | remove all memory leaks (CVS 80) (check-in: bf98cf82a7 user: drh tags: trunk) | |
11:25 | :-) (CVS 79) (check-in: 305b043f4f user: drh tags: trunk) | |
Changes
Changes to src/build.c.
︙ | ︙ | |||
29 30 31 32 33 34 35 | ** DROP TABLE ** CREATE INDEX ** DROP INDEX ** creating expressions and ID lists ** COPY ** VACUUM ** | | | 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | ** DROP TABLE ** CREATE INDEX ** DROP INDEX ** creating expressions and ID lists ** COPY ** VACUUM ** ** $Id: build.c,v 1.17 2000/06/08 13:36:40 drh Exp $ */ #include "sqliteInt.h" /* ** This routine is called after a single SQL statement has been ** parsed and we want to execute the code to implement ** the statement. Prior action routines should have already |
︙ | ︙ | |||
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 | sqliteFree(pTable->aCol[i].zName); sqliteFree(pTable->aCol[i].zDflt); } for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){ pNext = pIndex->pNext; sqliteDeleteIndex(db, pIndex); } sqliteFree(pTable->aCol); sqliteFree(pTable); } /* ** Construct the name of a user table from a token. ** ** Space to hold the name is obtained from sqliteMalloc() and must ** be freed by the calling function. */ char *sqliteTableNameFromToken(Token *pName){ | > | < | 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 | sqliteFree(pTable->aCol[i].zName); sqliteFree(pTable->aCol[i].zDflt); } for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){ pNext = pIndex->pNext; sqliteDeleteIndex(db, pIndex); } sqliteFree(pTable->zName); sqliteFree(pTable->aCol); sqliteFree(pTable); } /* ** Construct the name of a user table from a token. ** ** Space to hold the name is obtained from sqliteMalloc() and must ** be freed by the calling function. */ char *sqliteTableNameFromToken(Token *pName){ char *zName = sqliteStrNDup(pName->z, pName->n); sqliteDequote(zName); return zName; } /* ** Begin constructing a new table representation in memory. This is ** the first of several action routines that get called in response |
︙ | ︙ |
Changes to src/expr.c.
︙ | ︙ | |||
19 20 21 22 23 24 25 | ** Author contact information: ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ************************************************************************* ** This file contains C code routines used for processing expressions ** | | | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | ** Author contact information: ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ************************************************************************* ** This file contains C code routines used for processing expressions ** ** $Id: expr.c,v 1.13 2000/06/08 13:36:40 drh Exp $ */ #include "sqliteInt.h" /* ** Walk an expression tree. Return 1 if the expression is constant ** and 0 if it involves variables. */ |
︙ | ︙ | |||
114 115 116 117 118 119 120 | int sqliteExprResolveIds(Parse *pParse, IdList *pTabList, Expr *pExpr){ if( pExpr==0 ) return 0; switch( pExpr->op ){ /* A lone identifier */ case TK_ID: { int cnt = 0; /* Number of matches */ int i; /* Loop counter */ | < | | 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | int sqliteExprResolveIds(Parse *pParse, IdList *pTabList, Expr *pExpr){ if( pExpr==0 ) return 0; switch( pExpr->op ){ /* A lone identifier */ case TK_ID: { int cnt = 0; /* Number of matches */ int i; /* Loop counter */ char *z = sqliteStrNDup(pExpr->token.z, pExpr->token.n); for(i=0; i<pTabList->nId; i++){ int j; Table *pTab = pTabList->a[i].pTab; if( pTab==0 ) continue; for(j=0; j<pTab->nCol; j++){ if( sqliteStrICmp(pTab->aCol[j].zName, z)==0 ){ cnt++; |
︙ | ︙ | |||
155 156 157 158 159 160 161 | Expr *pLeft, *pRight; /* Left and right subbranches of the expr */ char *zLeft, *zRight; /* Text of an identifier */ pLeft = pExpr->pLeft; pRight = pExpr->pRight; assert( pLeft && pLeft->op==TK_ID ); assert( pRight && pRight->op==TK_ID ); | < | < | | 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 | Expr *pLeft, *pRight; /* Left and right subbranches of the expr */ char *zLeft, *zRight; /* Text of an identifier */ pLeft = pExpr->pLeft; pRight = pExpr->pRight; assert( pLeft && pLeft->op==TK_ID ); assert( pRight && pRight->op==TK_ID ); 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; Table *pTab = pTabList->a[i].pTab; if( pTab==0 ) continue; if( pTabList->a[i].zAlias ){ zTab = pTabList->a[i].zAlias; |
︙ | ︙ | |||
508 509 510 511 512 513 514 | sqliteExprCode(pParse, pExpr->pLeft); sqliteExprCode(pParse, pExpr->pRight); dest = sqliteVdbeCurrentAddr(v) + 2; sqliteVdbeAddOp(v, op, 0, dest, 0, 0); sqliteVdbeAddOp(v, OP_AddImm, -1, 0, 0, 0); break; } | | > > > > > > > > > > > > > > > | | 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 | sqliteExprCode(pParse, pExpr->pLeft); sqliteExprCode(pParse, pExpr->pRight); dest = sqliteVdbeCurrentAddr(v) + 2; sqliteVdbeAddOp(v, op, 0, dest, 0, 0); sqliteVdbeAddOp(v, OP_AddImm, -1, 0, 0, 0); break; } 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; } case TK_ISNULL: case TK_NOTNULL: { int dest; |
︙ | ︙ |
Changes to src/parse.y.
︙ | ︙ | |||
22 23 24 25 26 27 28 | ** ************************************************************************* ** This file contains SQLite's grammar for SQL. Process this file ** using the lemon parser generator to generate C code that runs ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** | | | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | ** ************************************************************************* ** This file contains SQLite's grammar for SQL. Process this file ** using the lemon parser generator to generate C code that runs ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** ** @(#) $Id: parse.y,v 1.17 2000/06/08 13:36:40 drh Exp $ */ %token_prefix TK_ %token_type {Token} %extra_argument {Parse *pParse} %syntax_error { sqliteSetNString(&pParse->zErrMsg,"syntax error near \"",0,TOKEN.z,TOKEN.n, "\"", 1, 0); |
︙ | ︙ | |||
267 268 269 270 271 272 273 | %destructor item {sqliteExprDelete($$);} itemlist(A) ::= itemlist(X) COMMA item(Y). {A = sqliteExprListAppend(X,Y,0);} 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). { | | < | | < | | 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 | %destructor item {sqliteExprDelete($$);} itemlist(A) ::= itemlist(X) COMMA item(Y). {A = sqliteExprListAppend(X,Y,0);} 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_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_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);} %type fieldlist_opt {IdList*} %destructor fieldlist_opt {sqliteIdListDelete($$);} %type fieldlist {IdList*} |
︙ | ︙ |
Changes to src/select.c.
︙ | ︙ | |||
20 21 22 23 24 25 26 | ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle SELECT statements. ** | | | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle SELECT statements. ** ** $Id: select.c,v 1.22 2000/06/08 13:36:40 drh Exp $ */ #include "sqliteInt.h" /* ** Allocate a new Select structure and return a pointer to that ** structure. */ |
︙ | ︙ | |||
140 141 142 143 144 145 146 147 148 149 150 151 152 153 | if( zSortOrder==0 ) return 1; for(i=0; i<pOrderBy->nExpr; i++){ zSortOrder[i] = pOrderBy->a[i].sortOrder ? '-' : '+'; sqliteExprCode(pParse, pOrderBy->a[i].pExpr); } zSortOrder[pOrderBy->nExpr] = 0; sqliteVdbeAddOp(v, OP_SortMakeKey, pOrderBy->nExpr, 0, zSortOrder, 0); sqliteVdbeAddOp(v, OP_SortPut, 0, 0, 0, 0); }else /* In this mode, write each query result to the key of the temporary ** table iParm. */ if( eDest==SRT_Union ){ | > | 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | if( zSortOrder==0 ) return 1; for(i=0; i<pOrderBy->nExpr; i++){ zSortOrder[i] = pOrderBy->a[i].sortOrder ? '-' : '+'; sqliteExprCode(pParse, pOrderBy->a[i].pExpr); } zSortOrder[pOrderBy->nExpr] = 0; sqliteVdbeAddOp(v, OP_SortMakeKey, pOrderBy->nExpr, 0, zSortOrder, 0); sqliteFree(zSortOrder); sqliteVdbeAddOp(v, OP_SortPut, 0, 0, 0, 0); }else /* In this mode, write each query result to the key of the temporary ** table iParm. */ if( eDest==SRT_Union ){ |
︙ | ︙ | |||
374 375 376 377 378 379 380 | for(i=0; i<pOrderBy->nExpr; i++){ Expr *pE = pOrderBy->a[i].pExpr; int match = 0; if( pOrderBy->a[i].done ) continue; 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; | | < > | 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 | for(i=0; i<pOrderBy->nExpr; i++){ Expr *pE = pOrderBy->a[i].pExpr; int match = 0; if( pOrderBy->a[i].done ) continue; 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 = 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; } if( match ){ pE->op = TK_FIELD; pE->iField = j; |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
19 20 21 22 23 24 25 | ** Author contact information: ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ************************************************************************* ** Internal interface definitions for SQLite. ** | | > > > > > > > > > > > > | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | ** Author contact information: ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.23 2000/06/08 13:36:40 drh Exp $ */ #include "sqlite.h" #include "dbbe.h" #include "vdbe.h" #include "parse.h" #include <gdbm.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> /* #define MEMORY_DEBUG 1 */ #ifdef MEMORY_DEBUG # 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. */ #define N_HASH 51 /* |
︙ | ︙ | |||
302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 | int sqliteHashNoCase(const char *, int); int sqliteCompare(const char *, const char *); int sqliteSortCompare(const char *, const char *); #ifdef MEMORY_DEBUG void *sqliteMalloc_(int,char*,int); void sqliteFree_(void*,char*,int); void *sqliteRealloc_(void*,int,char*,int); #else void *sqliteMalloc(int); void sqliteFree(void*); void *sqliteRealloc(void*,int); #endif int sqliteGetToken(const char*, int *); void sqliteSetString(char **, const char *, ...); void sqliteSetNString(char **, ...); void sqliteDequote(char*); int sqliteRunParser(Parse*, char*, char **); void sqliteExec(Parse*); | > > > > | 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 | int sqliteHashNoCase(const char *, int); int sqliteCompare(const char *, const char *); int sqliteSortCompare(const char *, const char *); #ifdef MEMORY_DEBUG 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 *, ...); void sqliteSetNString(char **, ...); void sqliteDequote(char*); int sqliteRunParser(Parse*, char*, char **); void sqliteExec(Parse*); |
︙ | ︙ |
Changes to src/tokenize.c.
︙ | ︙ | |||
23 24 25 26 27 28 29 | ************************************************************************* ** An tokenizer for SQL ** ** This file contains C code that splits an SQL input string up into ** individual tokens and sends those tokens one-by-one over to the ** parser for analysis. ** | | | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | ************************************************************************* ** An tokenizer for SQL ** ** This file contains C code that splits an SQL input string up into ** individual tokens and sends those tokens one-by-one over to the ** parser for analysis. ** ** $Id: tokenize.c,v 1.10 2000/06/08 13:36:40 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> #include <stdlib.h> /* ** All the keywords of the SQL language are stored as in a hash |
︙ | ︙ | |||
324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 | case TK_SPACE: break; case TK_COMMENT: { /* Various debugging modes can be turned on and off using ** special SQL comments. Check for the special comments ** here and take approriate action if found. */ char *z = pParse->sLastToken.z; if( sqliteStrNICmp(z,"--parser-trace-on--",19)==0 ){ trace = stderr; sqliteParserTrace(trace, "parser: "); }else if( sqliteStrNICmp(z,"--parser-trace-off--", 20)==0 ){ trace = 0; sqliteParserTrace(trace, "parser: "); }else if( sqliteStrNICmp(z,"--vdbe-trace-on--",17)==0 ){ pParse->db->flags |= SQLITE_VdbeTrace; }else if( sqliteStrNICmp(z,"--vdbe-trace-off--", 18)==0 ){ pParse->db->flags &= ~SQLITE_VdbeTrace; | > > > > > > > > > > > > > > > > > | > > > | > > | > > > | 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 | case TK_SPACE: break; case TK_COMMENT: { /* Various debugging modes can be turned on and off using ** 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; sqliteParserTrace(trace, "parser: "); }else if( sqliteStrNICmp(z,"--parser-trace-off--", 20)==0 ){ trace = 0; sqliteParserTrace(trace, "parser: "); }else if( sqliteStrNICmp(z,"--vdbe-trace-on--",17)==0 ){ 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: sqliteSetNString(pzErrMsg, "illegal token: \"", -1, pParse->sLastToken.z, pParse->sLastToken.n, 0); nErr++; break; default: sqliteParser(pEngine, tokenType, pParse->sLastToken, pParse); 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 && 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); } if( !nErr ) nErr++; } if( pParse->pVdbe ){ |
︙ | ︙ |
Changes to src/util.c.
︙ | ︙ | |||
22 23 24 25 26 27 28 | ** ************************************************************************* ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** | | > > > > > | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | ** ************************************************************************* ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** ** $Id: util.c,v 1.12 2000/06/08 13:36:41 drh Exp $ */ #include "sqliteInt.h" #include <stdarg.h> #include <ctype.h> #ifdef MEMORY_DEBUG /* ** Allocate new memory and set it to zero. Return NULL if ** no memory is available. */ 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; pi[0] = 0xdead1122; pi[1] = n; pi[k+2] = 0xdead3344; p = &pi[2]; |
︙ | ︙ | |||
61 62 63 64 65 66 67 68 69 70 71 72 73 74 | ** Free memory previously obtained from sqliteMalloc() */ void sqliteFree_(void *p, char *zFile, int line){ if( p ){ int *pi, k, n; pi = p; pi -= 2; if( pi[0]!=0xdead1122 ){ fprintf(stderr,"Low-end memory corruption at 0x%x\n", (int)p); return; } n = pi[1]; k = (n+sizeof(int)-1)/sizeof(int); if( pi[k+2]!=0xdead3344 ){ | > | 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | ** Free memory previously obtained from sqliteMalloc() */ void sqliteFree_(void *p, char *zFile, int line){ if( p ){ 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; } n = pi[1]; k = (n+sizeof(int)-1)/sizeof(int); if( pi[k+2]!=0xdead3344 ){ |
︙ | ︙ | |||
119 120 121 122 123 124 125 | memcpy(p, oldP, n>oldN ? oldN : n); if( n>oldN ){ memset(&((char*)p)[oldN], 0, n-oldN); } memset(oldPi, 0, (oldK+3)*sizeof(int)); free(oldPi); #if MEMORY_DEBUG>1 | | > > > > > > > > > > > > > > > > > > | 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 | memcpy(p, oldP, n>oldN ? oldN : n); if( n>oldN ){ memset(&((char*)p)[oldN], 0, n-oldN); } memset(oldPi, 0, (oldK+3)*sizeof(int)); free(oldPi); #if MEMORY_DEBUG>1 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; } /* ** Make a duplicate of a string into memory obtained from malloc() ** Free the original string using sqliteFree(). */ void sqliteStrRealloc(char **pz){ char *zNew; if( pz==0 || *pz==0 ) return; zNew = malloc( strlen(*pz) + 1 ); if( zNew ) strcpy(zNew, *pz); sqliteFree(*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 ** no memory is available. */ void *sqliteMalloc(int n){ |
︙ | ︙ | |||
174 175 176 177 178 179 180 181 182 183 184 185 186 187 | } if( n==0 ){ sqliteFree(p); return 0; } return realloc(p, n); } #endif /* MEMORY_DEBUG */ /* ** Create a string from the 2nd and subsequent arguments (up to the ** first NULL argument), store the string in memory obtained from ** sqliteMalloc() and make the pointer indicated by the 1st argument ** point to that string. | > > > > > > > > > > > > > > > > > | 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 | } if( n==0 ){ sqliteFree(p); return 0; } 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 */ /* ** Create a string from the 2nd and subsequent arguments (up to the ** first NULL argument), store the string in memory obtained from ** sqliteMalloc() and make the pointer indicated by the 1st argument ** point to that string. |
︙ | ︙ | |||
206 207 208 209 210 211 212 213 214 215 216 217 218 219 | zResult += strlen(zResult); va_start(ap, zFirst); while( (z = va_arg(ap, const char*))!=0 ){ strcpy(zResult, z); zResult += strlen(zResult); } va_end(ap); } /* ** Works like sqliteSetString, but each string is now followed by ** a length integer. -1 means use the whole string. */ void sqliteSetNString(char **pz, ...){ | > > > > > | 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 | zResult += strlen(zResult); va_start(ap, zFirst); while( (z = va_arg(ap, const char*))!=0 ){ strcpy(zResult, z); 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 } /* ** Works like sqliteSetString, but each string is now followed by ** a length integer. -1 means use the whole string. */ void sqliteSetNString(char **pz, ...){ |
︙ | ︙ | |||
239 240 241 242 243 244 245 246 247 248 249 250 251 252 | while( (z = va_arg(ap, const char*))!=0 ){ n = va_arg(ap, int); if( n<=0 ) n = strlen(z); strncpy(zResult, z, n); zResult += n; } *zResult = 0; va_end(ap); } /* ** Convert an SQL-style quoted string into a normal string by removing ** the quote characters. The conversion is done in-place. If the ** input does not begin with a quote character, then this routine | > > > > > | 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 | while( (z = va_arg(ap, const char*))!=0 ){ n = va_arg(ap, int); if( n<=0 ) n = strlen(z); strncpy(zResult, z, n); 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); } /* ** Convert an SQL-style quoted string into a normal string by removing ** the quote characters. The conversion is done in-place. If the ** input does not begin with a quote character, then this routine |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
37 38 39 40 41 42 43 | ** inplicit conversion from one type to the other occurs as necessary. ** ** Most of the code in this file is taken up by the sqliteVdbeExec() ** function which does the work of interpreting a VDBE program. ** But other routines are also provided to help in building up ** a program instruction by instruction. ** | | | 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | ** inplicit conversion from one type to the other occurs as necessary. ** ** Most of the code in this file is taken up by the sqliteVdbeExec() ** function which does the work of interpreting a VDBE program. ** But other routines are also provided to help in building up ** a program instruction by instruction. ** ** $Id: vdbe.c,v 1.28 2000/06/08 13:36:41 drh Exp $ */ #include "sqliteInt.h" #include <unistd.h> /* ** SQL is translated into a sequence of instructions to be ** executed by a virtual machine. Each instruction is an instance |
︙ | ︙ | |||
250 251 252 253 254 255 256 | p->aOp[i].opcode = op; p->aOp[i].p1 = p1; if( p2<0 && (-1-p2)<p->nLabel && p->aLabel[-1-p2]>=0 ){ p2 = p->aLabel[-1-p2]; } p->aOp[i].p2 = p2; if( p3 && p3[0] ){ | | | 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 | p->aOp[i].opcode = op; p->aOp[i].p1 = p1; if( p2<0 && (-1-p2)<p->nLabel && p->aLabel[-1-p2]>=0 ){ p2 = p->aLabel[-1-p2]; } p->aOp[i].p2 = p2; if( p3 && p3[0] ){ p->aOp[i].p3 = sqliteStrDup(p3); }else{ p->aOp[i].p3 = 0; } if( lbl<0 && (-lbl)<=p->nLabel ){ p->aLabel[-1-lbl] = i; for(j=0; j<i; j++){ if( p->aOp[j].p2==lbl ) p->aOp[j].p2 = i; |
︙ | ︙ | |||
519 520 521 522 523 524 525 | sprintf(zBuf,"%d",p->aStack[i].i); }else{ p->zStack[i] = ""; p->aStack[i].n = 1; p->aStack[i].flags |= STK_Str; return 0; } | | < | 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 | sprintf(zBuf,"%d",p->aStack[i].i); }else{ p->zStack[i] = ""; p->aStack[i].n = 1; p->aStack[i].flags |= STK_Str; return 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; return 0; } /* |
︙ | ︙ | |||
842 843 844 845 846 847 848 | pTail->pNext = pLeft; }else if( pRight ){ pTail->pNext = pRight; } return sHead.pNext; } | < | 841 842 843 844 845 846 847 848 849 850 851 852 853 854 | pTail->pNext = pLeft; }else if( pRight ){ pTail->pNext = pRight; } return sHead.pNext; } /* ** Execute the program in the VDBE. ** ** If an error occurs, an error message is written to memory obtained ** from sqliteMalloc() and *pzErrMsg is made to point to that memory. ** The return parameter is the number of errors. ** |
︙ | ︙ | |||
882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 | if( access("vdbe_trace",0)==0 ){ p->trace = stderr; } #endif /* if( pzErrMsg ){ *pzErrMsg = 0; } */ for(pc=0; rc==SQLITE_OK && pc<p->nOp && pc>=0; pc++){ pOp = &p->aOp[pc]; if( p->trace ){ fprintf(p->trace,"%4d %-12s %4d %4d %s\n", pc, zOpName[pOp->opcode], pOp->p1, pOp->p2, pOp->p3 ? pOp->p3 : ""); } switch( pOp->opcode ){ /* Opcode: Goto P2 * * ** ** An unconditional jump to address P2. ** The next instruction executed will be ** the one at index P2 from the beginning of ** the program. | > > > > > > | 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 | if( access("vdbe_trace",0)==0 ){ p->trace = stderr; } #endif /* 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 * * ** ** An unconditional jump to address P2. ** The next instruction executed will be ** the one at index P2 from the beginning of ** the program. |
︙ | ︙ | |||
1889 1890 1891 1892 1893 1894 1895 | ** Turn the key-as-data mode for cursor P1 either on (if P2==1) or ** off (if P2==0). In key-as-data mode, the OP_Fetch opcode pulls ** data off of the key rather than the data. This is useful for ** outer joins and stuff... */ case OP_KeyAsData: { int i = pOp->p1; | < | 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 | ** Turn the key-as-data mode for cursor P1 either on (if P2==1) or ** off (if P2==0). In key-as-data mode, the OP_Fetch opcode pulls ** data off of the key rather than the data. This is useful for ** outer joins and stuff... */ case OP_KeyAsData: { int i = pOp->p1; if( i>=0 && i<p->nTable && p->aTab[i].pTable!=0 ){ p->aTab[i].keyAsData = pOp->p2; } break; } /* Opcode: Field P1 P2 * |
︙ | ︙ | |||
2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 | ** location P1. P1 should be a small integer since space is allocated ** for all memory locations between 0 and P1 inclusive. */ case OP_MemStore: { int i = pOp->p1; int tos = p->tos; Mem *pMem; if( tos<0 ) goto not_enough_stack; if( i>=p->nMem ){ int nOld = p->nMem; p->nMem = i + 5; p->aMem = sqliteRealloc(p->aMem, p->nMem*sizeof(p->aMem[0])); if( p->aMem==0 ) goto no_mem; if( nOld<p->nMem ){ memset(&p->aMem[nOld], 0, sizeof(p->aMem[0])*(p->nMem-nOld)); } } pMem = &p->aMem[i]; if( pMem->s.flags & STK_Dyn ){ | > | > > | < > | 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 | ** location P1. P1 should be a small integer since space is allocated ** for all memory locations between 0 and P1 inclusive. */ case OP_MemStore: { 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; p->nMem = i + 5; p->aMem = sqliteRealloc(p->aMem, p->nMem*sizeof(p->aMem[0])); if( p->aMem==0 ) goto no_mem; if( nOld<p->nMem ){ memset(&p->aMem[nOld], 0, sizeof(p->aMem[0])*(p->nMem-nOld)); } } pMem = &p->aMem[i]; 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 = sqliteStrNDup(p->zStack[tos], pMem->s.n); pMem->s.flags |= STK_Dyn; } if( zOld ) sqliteFree(zOld); PopStack(p, 1); break; } /* Opcode: MemLoad P1 * * ** ** Push a copy of the value in memory location P1 onto the stack. |
︙ | ︙ | |||
2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 | AggElem *pFocus = AggInFocus(p->agg); int i = pOp->p2; int tos = p->tos; if( tos<0 ) goto not_enough_stack; if( pFocus==0 ) goto no_mem; if( i>=0 && i<p->agg.nMem ){ Mem *pMem = &pFocus->aMem[i]; pMem->s = p->aStack[tos]; if( pMem->s.flags & STK_Str ){ pMem->z = sqliteMalloc( p->aStack[tos].n ); if( pMem->z==0 ) goto no_mem; memcpy(pMem->z, p->zStack[tos], pMem->s.n); pMem->s.flags |= STK_Str|STK_Dyn; } } PopStack(p, 1); break; } /* Opcode: AggGet * P2 * ** | > > > > > > > | 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 | AggElem *pFocus = AggInFocus(p->agg); int i = pOp->p2; int tos = p->tos; if( tos<0 ) goto not_enough_stack; 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 ); if( pMem->z==0 ) goto no_mem; memcpy(pMem->z, p->zStack[tos], pMem->s.n); pMem->s.flags |= STK_Str|STK_Dyn; } if( zOld ) sqliteFree(zOld); } PopStack(p, 1); break; } /* Opcode: AggGet * P2 * ** |
︙ | ︙ | |||
2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 | default: { sprintf(zBuf,"%d",pOp->opcode); sqliteSetString(pzErrMsg, "unknown opcode ", zBuf, 0); rc = SQLITE_INTERNAL; break; } } if( pc<-1 || pc>=p->nOp ){ sqliteSetString(pzErrMsg, "jump destination out of range", 0); rc = SQLITE_INTERNAL; } if( p->trace && p->tos>=0 ){ int i; fprintf(p->trace, "Stack:"); | > > > > > > > | 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 | default: { sprintf(zBuf,"%d",pOp->opcode); sqliteSetString(pzErrMsg, "unknown opcode ", zBuf, 0); rc = SQLITE_INTERNAL; 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; } if( p->trace && p->tos>=0 ){ int i; fprintf(p->trace, "Stack:"); |
︙ | ︙ | |||
2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 | } }else{ fprintf(p->trace, " ???"); } } fprintf(p->trace,"\n"); } } cleanup: Cleanup(p); return rc; /* Jump to here if a malloc() fails. It's hard to get a malloc() | > | 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 | } }else{ fprintf(p->trace, " ???"); } } fprintf(p->trace,"\n"); } #endif } cleanup: Cleanup(p); return rc; /* Jump to here if a malloc() fails. It's hard to get a malloc() |
︙ | ︙ |
Changes to test/tester.tcl.
︙ | ︙ | |||
19 20 21 22 23 24 25 | # drh@hwaci.com # http://www.hwaci.com/drh/ # #*********************************************************************** # This file implements some common TCL routines used for regression # testing the SQLite library # | | | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | # drh@hwaci.com # http://www.hwaci.com/drh/ # #*********************************************************************** # This file implements some common TCL routines used for regression # testing the SQLite library # # $Id: tester.tcl,v 1.5 2000/06/08 13:36:41 drh Exp $ # Create a test database # file delete -force testdb file mkdir testdb sqlite db testdb |
︙ | ︙ | |||
70 71 72 73 74 75 76 77 78 79 80 81 82 83 | } } # Run this routine last # proc finish_test {} { global nTest nErr puts "$nErr errors out of $nTest tests" exit $nErr } # A procedure to execute SQL # proc execsql {sql} { | > | 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | } } # Run this routine last # proc finish_test {} { global nTest nErr catch {db close} puts "$nErr errors out of $nTest tests" exit $nErr } # A procedure to execute SQL # proc execsql {sql} { |
︙ | ︙ |
Added tool/memleak.awk.
> > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 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] } } |