/ Check-in [4aeb3ae4]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add extra assert() statements trying to catch a Mem object in an inconsistent state.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | enhanced-mem-check
Files: files | file ages | folders
SHA1:4aeb3ae435c78070232fef21a147fde4e1c5cd31
User & Date: drh 2014-03-01 14:45:18
Context
2014-03-01
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: 354699d5 user: drh tags: enhanced-mem-check
14:45
Add extra assert() statements trying to catch a Mem object in an inconsistent state. check-in: 4aeb3ae4 user: drh tags: enhanced-mem-check
2014-02-28
20:47
In the command-line shell add the (undocumented and unsupported) ".eqp" command and -eqp command-line option, to cause EXPLAIN QUERY PLAN to be run on each SQL statement as it is evaluated. Intended use is for analysis of the query planner. check-in: e6ecf733 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/vdbe.c.

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
....
2456
2457
2458
2459
2460
2461
2462

2463
2464
2465
2466
2467
2468
2469

    /* 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]) );

      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]) );

      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]) );

      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]);
    }
................................................................................

  /* 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 );

  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 */







>






>






>







 







>







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
....
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473

    /* 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( memSanity1(&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( memSanity1(&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( memSanity1(&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]);
    }
................................................................................

  /* 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( memSanity1(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


















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).
*/







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
** 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

/*
** A sanity check on a Mem object and especially the Mem.z field.
** This check says that no more than one of the following may be true:
**   (1) Mem.z comes from Mem.zMalloc
**   (2) Mem.z has a destructor Mem.xDel
**   (3) Mem.z is an ephemeral string
**   (4) Mem.z is a static string
**
** Use only inside of an assert() as follows:  assert( memSanify(pMem) );
*/
#ifdef SQLITE_DEBUG
#define memSanity1(p)                                  \
   ((((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 )
#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).
*/

Changes to src/vdbeaux.c.

1216
1217
1218
1219
1220
1221
1222

1223
1224
1225
1226
1227
1228
1229
      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 );


      /* 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 







>







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( memSanity1(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.

63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
...
288
289
290
291
292
293
294

295
296
297
298
299
300
301
**
** 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( 1 >=
    ((pMem->zMalloc && pMem->zMalloc==pMem->z) ? 1 : 0) +
    (((pMem->flags&MEM_Dyn)&&pMem->xDel) ? 1 : 0) + 
    ((pMem->flags&MEM_Ephem) ? 1 : 0) + 
    ((pMem->flags&MEM_Static) ? 1 : 0)
  );
  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 );

................................................................................

/*
** 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){

  VdbeMemRelease(p);
  if( p->zMalloc ){
    sqlite3DbFree(p->db, p->zMalloc);
    p->zMalloc = 0;
  }
  p->z = 0;
  assert( p->xDel==0 );  /* Zeroed by VdbeMemRelease() above */







|
<
<
<
<
<







 







>







63
64
65
66
67
68
69
70





71
72
73
74
75
76
77
...
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
**
** 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( memSanity1(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 );

................................................................................

/*
** 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( memSanity1(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 */