Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Factor the Mem invariant checker into a separate procedure (rather than a macro) so that it can be more easily extended. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | enhanced-mem-check |
Files: | files | file ages | folders |
SHA1: |
354699d50e7d251504a7b3d6fbec9e5b |
User & Date: | drh 2014-03-01 16:24:44.768 |
Context
2014-03-01
| ||
18:13 | Change the MEM_Dyn flag so that it means that Mem.xDel exists and must be used to free the string or blob. Add tighter invariant checks on Mem. (Closed-Leaf check-in: 44e1c33767 user: drh tags: enhanced-mem-check) | |
16:24 | Factor the Mem invariant checker into a separate procedure (rather than a macro) so that it can be more easily extended. (check-in: 354699d50e user: drh tags: enhanced-mem-check) | |
14:45 | Add extra assert() statements trying to catch a Mem object in an inconsistent state. (check-in: 4aeb3ae435 user: drh tags: enhanced-mem-check) | |
Changes
Changes to src/vdbe.c.
︙ | ︙ | |||
596 597 598 599 600 601 602 | /* Sanity checking on other operands */ #ifdef SQLITE_DEBUG if( (pOp->opflags & OPFLG_IN1)!=0 ){ assert( pOp->p1>0 ); assert( pOp->p1<=(p->nMem-p->nCursor) ); assert( memIsValid(&aMem[pOp->p1]) ); | | | | | 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 | /* Sanity checking on other operands */ #ifdef SQLITE_DEBUG if( (pOp->opflags & OPFLG_IN1)!=0 ){ assert( pOp->p1>0 ); assert( pOp->p1<=(p->nMem-p->nCursor) ); assert( memIsValid(&aMem[pOp->p1]) ); assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p1]) ); REGISTER_TRACE(pOp->p1, &aMem[pOp->p1]); } if( (pOp->opflags & OPFLG_IN2)!=0 ){ assert( pOp->p2>0 ); assert( pOp->p2<=(p->nMem-p->nCursor) ); assert( memIsValid(&aMem[pOp->p2]) ); assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p2]) ); REGISTER_TRACE(pOp->p2, &aMem[pOp->p2]); } if( (pOp->opflags & OPFLG_IN3)!=0 ){ assert( pOp->p3>0 ); assert( pOp->p3<=(p->nMem-p->nCursor) ); assert( memIsValid(&aMem[pOp->p3]) ); assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p3]) ); REGISTER_TRACE(pOp->p3, &aMem[pOp->p3]); } if( (pOp->opflags & OPFLG_OUT2)!=0 ){ assert( pOp->p2>0 ); assert( pOp->p2<=(p->nMem-p->nCursor) ); memAboutToChange(p, &aMem[pOp->p2]); } |
︙ | ︙ | |||
2459 2460 2461 2462 2463 2464 2465 | /* Extract the content for the p2+1-th column. Control can only ** reach this point if aOffset[p2], aOffset[p2+1], and aType[p2] are ** all valid. */ assert( p2<pC->nHdrParsed ); assert( rc==SQLITE_OK ); | | | 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 | /* Extract the content for the p2+1-th column. Control can only ** reach this point if aOffset[p2], aOffset[p2+1], and aType[p2] are ** all valid. */ assert( p2<pC->nHdrParsed ); assert( rc==SQLITE_OK ); assert( sqlite3VdbeCheckMemInvariants(pDest) ); if( pC->szRow>=aOffset[p2+1] ){ /* This is the common case where the desired content fits on the original ** page - where the content is not on an overflow page */ VdbeMemRelease(pDest); sqlite3VdbeSerialGet(pC->aRow+aOffset[p2], aType[p2], pDest); }else{ /* This branch happens only when content is on overflow pages */ |
︙ | ︙ |
Changes to src/vdbeInt.h.
︙ | ︙ | |||
228 229 230 231 232 233 234 | ** Return true if a memory cell is not marked as invalid. This macro ** is for use inside assert() statements only. */ #ifdef SQLITE_DEBUG #define memIsValid(M) ((M)->flags & MEM_Undefined)==0 #endif | < < < < < < < < < < < < < < < < < < | 228 229 230 231 232 233 234 235 236 237 238 239 240 241 | ** Return true if a memory cell is not marked as invalid. This macro ** is for use inside assert() statements only. */ #ifdef SQLITE_DEBUG #define memIsValid(M) ((M)->flags & MEM_Undefined)==0 #endif /* ** Each auxilliary data pointer stored by a user defined function ** implementation calling sqlite3_set_auxdata() is stored in an instance ** of this structure. All such structures associated with a single VM ** are stored in a linked list headed at Vdbe.pAuxData. All are destroyed ** when the VM is halted (if not before). */ |
︙ | ︙ | |||
470 471 472 473 474 475 476 477 478 479 480 481 482 483 | #else # define sqlite3VdbeEnter(X) # define sqlite3VdbeLeave(X) #endif #ifdef SQLITE_DEBUG void sqlite3VdbeMemAboutToChange(Vdbe*,Mem*); #endif #ifndef SQLITE_OMIT_FOREIGN_KEY int sqlite3VdbeCheckFk(Vdbe *, int); #else # define sqlite3VdbeCheckFk(p,i) 0 #endif | > | 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 | #else # define sqlite3VdbeEnter(X) # define sqlite3VdbeLeave(X) #endif #ifdef SQLITE_DEBUG void sqlite3VdbeMemAboutToChange(Vdbe*,Mem*); int sqlite3VdbeCheckMemInvariants(Mem*); #endif #ifndef SQLITE_OMIT_FOREIGN_KEY int sqlite3VdbeCheckFk(Vdbe *, int); #else # define sqlite3VdbeCheckFk(p,i) 0 #endif |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
1216 1217 1218 1219 1220 1221 1222 | for(pEnd=&p[N]; p<pEnd; p++){ sqlite3DbFree(db, p->zMalloc); } return; } for(pEnd=&p[N]; p<pEnd; p++){ assert( (&p[1])==pEnd || p[0].db==p[1].db ); | | | 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 | for(pEnd=&p[N]; p<pEnd; p++){ sqlite3DbFree(db, p->zMalloc); } return; } for(pEnd=&p[N]; p<pEnd; p++){ assert( (&p[1])==pEnd || p[0].db==p[1].db ); assert( sqlite3VdbeCheckMemInvariants(p) ); /* This block is really an inlined version of sqlite3VdbeMemRelease() ** that takes advantage of the fact that the memory cell value is ** being set to NULL after releasing any dynamic resources. ** ** The justification for duplicating code is that according to ** callgrind, this causes a certain test case to hit the CPU 4.7 |
︙ | ︙ |
Changes to src/vdbemem.c.
︙ | ︙ | |||
13 14 15 16 17 18 19 20 21 22 23 24 25 26 | ** This file contains code use to manipulate "Mem" structure. A "Mem" ** stores a single value in the VDBE. Mem is an opaque structure visible ** only within the VDBE. Interface routines refer to a Mem using the ** name sqlite_value */ #include "sqliteInt.h" #include "vdbeInt.h" /* ** If pMem is an object with a valid string representation, this routine ** ensures the internal encoding for the string representation is ** 'desiredEnc', one of SQLITE_UTF8, SQLITE_UTF16LE or SQLITE_UTF16BE. ** ** If pMem is not a string object, or the encoding of the string | > > > > > > > > > > > > > > > > > > | 13 14 15 16 17 18 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 | ** This file contains code use to manipulate "Mem" structure. A "Mem" ** stores a single value in the VDBE. Mem is an opaque structure visible ** only within the VDBE. Interface routines refer to a Mem using the ** name sqlite_value */ #include "sqliteInt.h" #include "vdbeInt.h" #ifdef SQLITE_DEBUG /* ** Check invariants on a Mem object. ** ** This routine is intended for use inside of assert() statements, like ** this: assert( sqlite3VdbeCheckMemInvariants(pMem) ); */ int sqlite3VdbeCheckMemInvariants(Mem *p){ assert( (((p)->zMalloc && (p)->zMalloc==(p)->z) ? 1 : 0) + ((((p)->flags&MEM_Dyn)&&(p)->xDel) ? 1 : 0) + (((p)->flags&MEM_Ephem) ? 1 : 0) + (((p)->flags&MEM_Static) ? 1 : 0) <= 1 ); return 1; } #endif /* ** If pMem is an object with a valid string representation, this routine ** ensures the internal encoding for the string representation is ** 'desiredEnc', one of SQLITE_UTF8, SQLITE_UTF16LE or SQLITE_UTF16BE. ** ** If pMem is not a string object, or the encoding of the string |
︙ | ︙ | |||
63 64 65 66 67 68 69 | ** ** If the bPreserve argument is true, then copy of the content of ** pMem->z into the new allocation. pMem must be either a string or ** blob if bPreserve is true. If bPreserve is false, any prior content ** in pMem->z is discarded. */ int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){ | | | 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | ** ** If the bPreserve argument is true, then copy of the content of ** pMem->z into the new allocation. pMem must be either a string or ** blob if bPreserve is true. If bPreserve is false, any prior content ** in pMem->z is discarded. */ int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){ assert( sqlite3VdbeCheckMemInvariants(pMem) ); assert( (pMem->flags&MEM_RowSet)==0 ); /* If the bPreserve flag is set to true, then the memory cell must already ** contain a valid string or blob value. */ assert( bPreserve==0 || pMem->flags&(MEM_Blob|MEM_Str) ); testcase( bPreserve && pMem->z==0 ); |
︙ | ︙ | |||
283 284 285 286 287 288 289 | /* ** Release any memory held by the Mem. This may leave the Mem in an ** inconsistent state, for example with (Mem.z==0) and ** (Mem.memType==MEM_Str). */ void sqlite3VdbeMemRelease(Mem *p){ | | | 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 | /* ** Release any memory held by the Mem. This may leave the Mem in an ** inconsistent state, for example with (Mem.z==0) and ** (Mem.memType==MEM_Str). */ void sqlite3VdbeMemRelease(Mem *p){ assert( sqlite3VdbeCheckMemInvariants(p) ); VdbeMemRelease(p); if( p->zMalloc ){ sqlite3DbFree(p->db, p->zMalloc); p->zMalloc = 0; } p->z = 0; assert( p->xDel==0 ); /* Zeroed by VdbeMemRelease() above */ |
︙ | ︙ |