/ Check-in [354699d5]
Login

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 | SQL archive
Timelines: family | ancestors | descendants | both | enhanced-mem-check
Files: files | file ages | folders
SHA1: 354699d50e7d251504a7b3d6fbec9e5bcf99557f
User & Date: drh 2014-03-01 16:24:44
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: 44e1c337 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: 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
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/vdbe.c.

   596    596   
   597    597       /* Sanity checking on other operands */
   598    598   #ifdef SQLITE_DEBUG
   599    599       if( (pOp->opflags & OPFLG_IN1)!=0 ){
   600    600         assert( pOp->p1>0 );
   601    601         assert( pOp->p1<=(p->nMem-p->nCursor) );
   602    602         assert( memIsValid(&aMem[pOp->p1]) );
   603         -      assert( memSanity1(&aMem[pOp->p1]) );
          603  +      assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p1]) );
   604    604         REGISTER_TRACE(pOp->p1, &aMem[pOp->p1]);
   605    605       }
   606    606       if( (pOp->opflags & OPFLG_IN2)!=0 ){
   607    607         assert( pOp->p2>0 );
   608    608         assert( pOp->p2<=(p->nMem-p->nCursor) );
   609    609         assert( memIsValid(&aMem[pOp->p2]) );
   610         -      assert( memSanity1(&aMem[pOp->p2]) );
          610  +      assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p2]) );
   611    611         REGISTER_TRACE(pOp->p2, &aMem[pOp->p2]);
   612    612       }
   613    613       if( (pOp->opflags & OPFLG_IN3)!=0 ){
   614    614         assert( pOp->p3>0 );
   615    615         assert( pOp->p3<=(p->nMem-p->nCursor) );
   616    616         assert( memIsValid(&aMem[pOp->p3]) );
   617         -      assert( memSanity1(&aMem[pOp->p3]) );
          617  +      assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p3]) );
   618    618         REGISTER_TRACE(pOp->p3, &aMem[pOp->p3]);
   619    619       }
   620    620       if( (pOp->opflags & OPFLG_OUT2)!=0 ){
   621    621         assert( pOp->p2>0 );
   622    622         assert( pOp->p2<=(p->nMem-p->nCursor) );
   623    623         memAboutToChange(p, &aMem[pOp->p2]);
   624    624       }
................................................................................
  2459   2459   
  2460   2460     /* Extract the content for the p2+1-th column.  Control can only
  2461   2461     ** reach this point if aOffset[p2], aOffset[p2+1], and aType[p2] are
  2462   2462     ** all valid.
  2463   2463     */
  2464   2464     assert( p2<pC->nHdrParsed );
  2465   2465     assert( rc==SQLITE_OK );
  2466         -  assert( memSanity1(pDest) );
         2466  +  assert( sqlite3VdbeCheckMemInvariants(pDest) );
  2467   2467     if( pC->szRow>=aOffset[p2+1] ){
  2468   2468       /* This is the common case where the desired content fits on the original
  2469   2469       ** page - where the content is not on an overflow page */
  2470   2470       VdbeMemRelease(pDest);
  2471   2471       sqlite3VdbeSerialGet(pC->aRow+aOffset[p2], aType[p2], pDest);
  2472   2472     }else{
  2473   2473       /* This branch happens only when content is on overflow pages */

Changes to src/vdbeInt.h.

   228    228   ** Return true if a memory cell is not marked as invalid.  This macro
   229    229   ** is for use inside assert() statements only.
   230    230   */
   231    231   #ifdef SQLITE_DEBUG
   232    232   #define memIsValid(M)  ((M)->flags & MEM_Undefined)==0
   233    233   #endif
   234    234   
   235         -/*
   236         -** A sanity check on a Mem object and especially the Mem.z field.
   237         -** This check says that no more than one of the following may be true:
   238         -**   (1) Mem.z comes from Mem.zMalloc
   239         -**   (2) Mem.z has a destructor Mem.xDel
   240         -**   (3) Mem.z is an ephemeral string
   241         -**   (4) Mem.z is a static string
   242         -**
   243         -** Use only inside of an assert() as follows:  assert( memSanify(pMem) );
   244         -*/
   245         -#ifdef SQLITE_DEBUG
   246         -#define memSanity1(p)                                  \
   247         -   ((((p)->zMalloc && (p)->zMalloc==(p)->z) ? 1 : 0) + \
   248         -    ((((p)->flags&MEM_Dyn)&&(p)->xDel) ? 1 : 0) +      \
   249         -    (((p)->flags&MEM_Ephem) ? 1 : 0) +                 \
   250         -    (((p)->flags&MEM_Static) ? 1 : 0) <= 1 )
   251         -#endif
   252         -
   253    235   /*
   254    236   ** Each auxilliary data pointer stored by a user defined function 
   255    237   ** implementation calling sqlite3_set_auxdata() is stored in an instance
   256    238   ** of this structure. All such structures associated with a single VM
   257    239   ** are stored in a linked list headed at Vdbe.pAuxData. All are destroyed
   258    240   ** when the VM is halted (if not before).
   259    241   */
................................................................................
   470    452   #else
   471    453   # define sqlite3VdbeEnter(X)
   472    454   # define sqlite3VdbeLeave(X)
   473    455   #endif
   474    456   
   475    457   #ifdef SQLITE_DEBUG
   476    458   void sqlite3VdbeMemAboutToChange(Vdbe*,Mem*);
          459  +int sqlite3VdbeCheckMemInvariants(Mem*);
   477    460   #endif
   478    461   
   479    462   #ifndef SQLITE_OMIT_FOREIGN_KEY
   480    463   int sqlite3VdbeCheckFk(Vdbe *, int);
   481    464   #else
   482    465   # define sqlite3VdbeCheckFk(p,i) 0
   483    466   #endif

Changes to src/vdbeaux.c.

  1216   1216         for(pEnd=&p[N]; p<pEnd; p++){
  1217   1217           sqlite3DbFree(db, p->zMalloc);
  1218   1218         }
  1219   1219         return;
  1220   1220       }
  1221   1221       for(pEnd=&p[N]; p<pEnd; p++){
  1222   1222         assert( (&p[1])==pEnd || p[0].db==p[1].db );
  1223         -      assert( memSanity1(p) );
         1223  +      assert( sqlite3VdbeCheckMemInvariants(p) );
  1224   1224   
  1225   1225         /* This block is really an inlined version of sqlite3VdbeMemRelease()
  1226   1226         ** that takes advantage of the fact that the memory cell value is 
  1227   1227         ** being set to NULL after releasing any dynamic resources.
  1228   1228         **
  1229   1229         ** The justification for duplicating code is that according to 
  1230   1230         ** callgrind, this causes a certain test case to hit the CPU 4.7 

Changes to src/vdbemem.c.

    13     13   ** This file contains code use to manipulate "Mem" structure.  A "Mem"
    14     14   ** stores a single value in the VDBE.  Mem is an opaque structure visible
    15     15   ** only within the VDBE.  Interface routines refer to a Mem using the
    16     16   ** name sqlite_value
    17     17   */
    18     18   #include "sqliteInt.h"
    19     19   #include "vdbeInt.h"
           20  +
           21  +#ifdef SQLITE_DEBUG
           22  +/*
           23  +** Check invariants on a Mem object.
           24  +**
           25  +** This routine is intended for use inside of assert() statements, like
           26  +** this:    assert( sqlite3VdbeCheckMemInvariants(pMem) );
           27  +*/
           28  +int sqlite3VdbeCheckMemInvariants(Mem *p){
           29  +  assert( 
           30  +    (((p)->zMalloc && (p)->zMalloc==(p)->z) ? 1 : 0) +
           31  +    ((((p)->flags&MEM_Dyn)&&(p)->xDel) ? 1 : 0) +
           32  +    (((p)->flags&MEM_Ephem) ? 1 : 0) +
           33  +    (((p)->flags&MEM_Static) ? 1 : 0) <= 1 );
           34  +  return 1;
           35  +}
           36  +#endif
           37  +
    20     38   
    21     39   /*
    22     40   ** If pMem is an object with a valid string representation, this routine
    23     41   ** ensures the internal encoding for the string representation is
    24     42   ** 'desiredEnc', one of SQLITE_UTF8, SQLITE_UTF16LE or SQLITE_UTF16BE.
    25     43   **
    26     44   ** If pMem is not a string object, or the encoding of the string
................................................................................
    63     81   **
    64     82   ** If the bPreserve argument is true, then copy of the content of
    65     83   ** pMem->z into the new allocation.  pMem must be either a string or
    66     84   ** blob if bPreserve is true.  If bPreserve is false, any prior content
    67     85   ** in pMem->z is discarded.
    68     86   */
    69     87   int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){
    70         -  assert( memSanity1(pMem) );
           88  +  assert( sqlite3VdbeCheckMemInvariants(pMem) );
    71     89     assert( (pMem->flags&MEM_RowSet)==0 );
    72     90   
    73     91     /* If the bPreserve flag is set to true, then the memory cell must already
    74     92     ** contain a valid string or blob value.  */
    75     93     assert( bPreserve==0 || pMem->flags&(MEM_Blob|MEM_Str) );
    76     94     testcase( bPreserve && pMem->z==0 );
    77     95   
................................................................................
   283    301   
   284    302   /*
   285    303   ** Release any memory held by the Mem. This may leave the Mem in an
   286    304   ** inconsistent state, for example with (Mem.z==0) and
   287    305   ** (Mem.memType==MEM_Str).
   288    306   */
   289    307   void sqlite3VdbeMemRelease(Mem *p){
   290         -  assert( memSanity1(p) );
          308  +  assert( sqlite3VdbeCheckMemInvariants(p) );
   291    309     VdbeMemRelease(p);
   292    310     if( p->zMalloc ){
   293    311       sqlite3DbFree(p->db, p->zMalloc);
   294    312       p->zMalloc = 0;
   295    313     }
   296    314     p->z = 0;
   297    315     assert( p->xDel==0 );  /* Zeroed by VdbeMemRelease() above */