]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add assert()s to mem2.c (activated by SQLITE_MEMDEBUG) which verify that
authordrh <drh@noemail.net>
Fri, 12 Mar 2010 16:32:53 +0000 (16:32 +0000)
committerdrh <drh@noemail.net>
Fri, 12 Mar 2010 16:32:53 +0000 (16:32 +0000)
memory alloctions that might have come from lookaside are always freed
using a lookaside-aware free routine.

FossilOrigin-Name: c2af2164cf7b279ebb3e08201561348be6e765df

manifest
manifest.uuid
src/malloc.c
src/mem2.c
src/pcache1.c
src/sqliteInt.h

index 8ba1605d0eea9d91dc9506cc7bde2d5051a03774..ba1349596de51369edca0fa677140bb3149f9e88 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,8 +1,8 @@
 -----BEGIN PGP SIGNED MESSAGE-----
 Hash: SHA1
 
-C Move\sthe\sctime.c\ssource\smodule\snear\sthe\sbeginning\sof\sthe\slist\sof\sfiles\ninserted\sinto\sthe\samalgamation\sso\sthat\s#defines\sthat\sare\soverridden\sin\nother\smodules\swill\snot\seffect\sthe\svalues\sreturned\sby\nsqlite3_compiletime_used().
-D 2010-03-10T23:13:54
+C Add\sassert()s\sto\smem2.c\s(activated\sby\sSQLITE_MEMDEBUG)\swhich\sverify\sthat\nmemory\salloctions\sthat\smight\shave\scome\sfrom\slookaside\sare\salways\sfreed\nusing\sa\slookaside-aware\sfree\sroutine.
+D 2010-03-12T16:32:54
 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
 F Makefile.in 4f2f967b7e58a35bb74fb7ec8ae90e0f4ca7868b
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -135,10 +135,10 @@ F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f
 F src/lempar.c 7f026423f4d71d989e719a743f98a1cbd4e6d99e
 F src/loadext.c 1c7a61ce1281041f437333f366a96aa0d29bb581
 F src/main.c 7d89bb6dcc6993a8d32f4f22dae3e57c50a41399
-F src/malloc.c 5fa175797f982b178eaf38afba9c588a866be729
+F src/malloc.c a08f16d134f0bfab6b20c3cd142ebf3e58235a6a
 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
 F src/mem1.c 89d4ea8d5cdd55635cbaa48ad53132af6294cbb2
-F src/mem2.c ee752297650632935218dcf3b20c5ed5899cb4b5
+F src/mem2.c 2ee7bdacda8299b5a91cff9f7ee3e46573195c38
 F src/mem3.c 9b237d911ba9904142a804be727cc6664873f8a3
 F src/mem5.c eb7a5cb98915dd7a086fa415ce3a5a0f20d0acff
 F src/memjournal.c 5bfc2f33c914946e2f77ed3f882aff14dfc9355d
@@ -160,7 +160,7 @@ F src/pager.h ef8a2cf10084f60ab45ee2dfded8bf8b0c655ddf
 F src/parse.y ace5c7a125d9f2a410e431ee3209034105045f7e
 F src/pcache.c 4956b41d6ba913f7a8a56fbf32be78caed0e45c2
 F src/pcache.h c683390d50f856d4cd8e24342ae62027d1bb6050
-F src/pcache1.c 2bb2261190b42a348038f5b1c285c8cef415fcc8
+F src/pcache1.c 6dc1871ce8ead9187161c370a58cd06c84221f76
 F src/pragma.c 56d95f76154a5f873c32eae485bb625f3c70be46
 F src/prepare.c 18292e5f365655cd5c5693e09508e90668f7d547
 F src/printf.c 5f5b65a83e63f2096a541a340722a509fa0240a7
@@ -171,7 +171,7 @@ F src/select.c 4113ef360430ed4e7533690ef46d06c20204adce
 F src/shell.c c40427c7245535a04a9cb4a417b6cc05c022e6a4
 F src/sqlite.h.in 30ff19c3a52f14cb0bd7c598f674068bccc22ccc
 F src/sqlite3ext.h 69dfb8116af51b84a029cddb3b35062354270c89
-F src/sqliteInt.h 4e411c08ff8d776272948abb861be32e4786eff8
+F src/sqliteInt.h f9b890585c644da05e86b772042ae2059e61fd27
 F src/sqliteLimit.h 3afab2291762b5d09ae20c18feb8e9fa935a60a6
 F src/status.c 4df6fe7dce2d256130b905847c6c60055882bdbe
 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
@@ -796,14 +796,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P 418c6d8113bc337556b0d47acfd6a7d865d1121f
-R 3f2b78a22e4875c367371e44fb59a9b0
+P bb591802fff5a99ae504509e812bb34e762eaef0
+R 186ecc2081ee65c0f8ee3d1b1372d8b0
 U drh
-Z 1cec0a12987695a8137fed791b404644
+Z 9c8eb30bbeb3dcf4398c4d7241d3ba9c
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.6 (GNU/Linux)
 
-iD8DBQFLmCe2oxKgR168RlERAn/ZAJ92sAWFQgbytu6nRt55fRcBoeokVQCbBVSd
-zrVOUqTy+bjHBsloTqu/hi4=
-=M3CA
+iD8DBQFLmmy5oxKgR168RlERAg8iAJ4rM9xkHfG/M6XD6ejNennKrxQDGwCgibIf
+n4ngbmeDUYGL/Jvz6Tn0drM=
+=FOIW
 -----END PGP SIGNATURE-----
index 3d8c9c4a323531a9a41c090f50af25d54dbb4624..13b3761aef01d2ecc64cff62b7beeb151183ddd7 100644 (file)
@@ -1 +1 @@
-bb591802fff5a99ae504509e812bb34e762eaef0
\ No newline at end of file
+c2af2164cf7b279ebb3e08201561348be6e765df
\ No newline at end of file
index 6b251876d3bf8cda39a30758dd72956fa2b56cee..6d3b3002ebd7e761522acec9b7be8e7a02c8b244 100644 (file)
@@ -356,6 +356,7 @@ scratch_overflow:
   }else{
     p = sqlite3GlobalConfig.m.xMalloc(n);
   }
+  sqlite3MemdebugSetType(p, MEMTYPE_SCRATCH);
 #if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
   scratchAllocOut = p!=0;
 #endif
@@ -376,6 +377,8 @@ void sqlite3ScratchFree(void *p){
     if( sqlite3GlobalConfig.pScratch==0
            || p<sqlite3GlobalConfig.pScratch
            || p>=(void*)mem0.aScratchFree ){
+      assert( sqlite3MemdebugHasType(p, MEMTYPE_SCRATCH) );
+      sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
       if( sqlite3GlobalConfig.bMemstat ){
         int iSize = sqlite3MallocSize(p);
         sqlite3_mutex_enter(mem0.mutex);
@@ -416,6 +419,7 @@ static int isLookaside(sqlite3 *db, void *p){
 ** sqlite3Malloc() or sqlite3_malloc().
 */
 int sqlite3MallocSize(void *p){
+  assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
   return sqlite3GlobalConfig.m.xSize(p);
 }
 int sqlite3DbMallocSize(sqlite3 *db, void *p){
@@ -423,6 +427,8 @@ int sqlite3DbMallocSize(sqlite3 *db, void *p){
   if( isLookaside(db, p) ){
     return db->lookaside.sz;
   }else{
+    assert( sqlite3MemdebugHasType(p,
+             db ? (MEMTYPE_DB|MEMTYPE_HEAP) : MEMTYPE_HEAP) );
     return sqlite3GlobalConfig.m.xSize(p);
   }
 }
@@ -432,6 +438,7 @@ int sqlite3DbMallocSize(sqlite3 *db, void *p){
 */
 void sqlite3_free(void *p){
   if( p==0 ) return;
+  assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
   if( sqlite3GlobalConfig.bMemstat ){
     sqlite3_mutex_enter(mem0.mutex);
     sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -sqlite3MallocSize(p));
@@ -454,6 +461,8 @@ void sqlite3DbFree(sqlite3 *db, void *p){
     db->lookaside.pFree = pBuf;
     db->lookaside.nOut--;
   }else{
+    assert( sqlite3MemdebugHasType(p, MEMTYPE_DB|MEMTYPE_HEAP) );
+    sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
     sqlite3_free(p);
   }
 }
@@ -486,6 +495,7 @@ void *sqlite3Realloc(void *pOld, int nBytes){
           mem0.alarmThreshold ){
       sqlite3MallocAlarm(nNew-nOld);
     }
+    assert( sqlite3MemdebugHasType(pOld, MEMTYPE_HEAP) );
     pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
     if( pNew==0 && mem0.alarmCallback ){
       sqlite3MallocAlarm(nBytes);
@@ -583,6 +593,8 @@ void *sqlite3DbMallocRaw(sqlite3 *db, int n){
   if( !p && db ){
     db->mallocFailed = 1;
   }
+  sqlite3MemdebugSetType(p,
+            (db && db->lookaside.bEnabled) ? MEMTYPE_DB : MEMTYPE_HEAP);
   return p;
 }
 
@@ -608,10 +620,14 @@ void *sqlite3DbRealloc(sqlite3 *db, void *p, int n){
         sqlite3DbFree(db, p);
       }
     }else{
+      assert( sqlite3MemdebugHasType(p, MEMTYPE_DB|MEMTYPE_HEAP) );
+      sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
       pNew = sqlite3_realloc(p, n);
       if( !pNew ){
         db->mallocFailed = 1;
       }
+      sqlite3MemdebugSetType(pNew,
+            db->lookaside.bEnabled ? MEMTYPE_DB : MEMTYPE_HEAP);
     }
   }
   return pNew;
index 5eb937ed4301113f8bbead96d7e286a9ae09e6bb..a82fee8fdb77845775abb06148dec10914bb69b1 100644 (file)
@@ -57,7 +57,8 @@ struct MemBlockHdr {
   struct MemBlockHdr *pNext, *pPrev;  /* Linked list of all unfreed memory */
   char nBacktrace;                    /* Number of backtraces on this alloc */
   char nBacktraceSlots;               /* Available backtrace slots */
-  short nTitle;                       /* Bytes of title; includes '\0' */
+  u8 nTitle;                          /* Bytes of title; includes '\0' */
+  u8 eType;                           /* Allocation type code */
   int iForeGuard;                     /* Guard word for sanity */
 };
 
@@ -265,6 +266,7 @@ static void *sqlite3MemMalloc(int nByte){
     }
     mem.pLast = pHdr;
     pHdr->iForeGuard = FOREGUARD;
+    pHdr->eType = MEMTYPE_HEAP;
     pHdr->nBacktraceSlots = mem.nBacktrace;
     pHdr->nTitle = mem.nTitle;
     if( mem.nBacktrace ){
@@ -372,6 +374,47 @@ void sqlite3MemSetDefault(void){
   sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods);
 }
 
+/*
+** Set the "type" of an allocation.
+*/
+void sqlite3MemdebugSetType(void *p, u8 eType){
+  if( p ){
+    struct MemBlockHdr *pHdr;
+    pHdr = sqlite3MemsysGetHeader(p);
+    assert( pHdr->iForeGuard==FOREGUARD );
+    pHdr->eType = eType;
+  }
+}
+
+/*
+** Return TRUE if the mask of type in eType matches the type of the
+** allocation p.  Also return true if p==NULL.
+**
+** This routine is designed for use within an assert() statement, to
+** verify the type of an allocation.  For example:
+**
+**     assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
+*/
+int sqlite3MemdebugHasType(void *p, u8 eType){
+  int rc = 1;
+  if( p ){
+    struct MemBlockHdr *pHdr;
+    pHdr = sqlite3MemsysGetHeader(p);
+    assert( pHdr->iForeGuard==FOREGUARD );         /* Allocation is valid */
+    assert( (pHdr->eType & (pHdr->eType-1))==0 );  /* Only one type bit set */
+    if( (pHdr->eType&eType)==0 ){
+      void **pBt;
+      pBt = (void**)pHdr;
+      pBt -= pHdr->nBacktraceSlots;
+      backtrace_symbols_fd(pBt, pHdr->nBacktrace, fileno(stderr));
+      fprintf(stderr, "\n");
+      rc = 0;
+    }
+  }
+  return rc;
+}
+
 /*
 ** Set the number of backtrace levels kept for each allocation.
 ** A value of zero turns off backtracing.  The number is always rounded
index a3bd0fcea8ff64d97f0ece4efdd3d35bb42c7b58..92cf5adb998757914f7f37d0fcf7bb1a5e049fb9 100644 (file)
@@ -173,6 +173,7 @@ static void *pcache1Alloc(int nByte){
       int sz = sqlite3MallocSize(p);
       sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz);
     }
+    sqlite3MemdebugSetType(p, MEMTYPE_PCACHE);
   }
   return p;
 }
@@ -190,7 +191,10 @@ static void pcache1Free(void *p){
     pSlot->pNext = pcache1.pFree;
     pcache1.pFree = pSlot;
   }else{
-    int iSize = sqlite3MallocSize(p);
+    int iSize;
+    assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) );
+    sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
+    iSize = sqlite3MallocSize(p);
     sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -iSize);
     sqlite3_free(p);
   }
index a21513d238c0f649be6e0228b0ae659aa948dc63..c674b71bd256162c3d033cbc992daf4059d731e6 100644 (file)
@@ -3089,4 +3089,43 @@ SQLITE_EXTERN void (*sqlite3IoTrace)(const char*,...);
 # define sqlite3VdbeIOTraceSql(X)
 #endif
 
+/*
+** These routines are available for the mem2.c debugging memory allocator
+** only.  They are used to verify that different "types" of memory
+** allocations are properly tracked by the system.
+**
+** sqlite3MemdebugSetType() sets the "type" of an allocation to one of
+** the MEMTYPE_* macros defined below.  The type must be a bitmask with
+** a single bit set.
+**
+** sqlite3MemdebugHasType() returns true if any of the bits in its second
+** argument match the type set by the previous sqlite3MemdebugSetType().
+** sqlite3MemdebugHasType() is intended for use inside assert() statements.
+** For example:
+**
+**     assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
+**
+** Perhaps the most important point is the difference between MEMTYPE_HEAP
+** and MEMTYPE_DB.  If an allocation is MEMTYPE_DB, that means it might have
+** been allocated by lookaside, except the allocation was too large or
+** lookaside was already full.  It is important to verify that allocations
+** that might have been satisfied by lookaside are not passed back to 
+** non-lookaside free() routines.  Asserts such as the example above are
+** placed on the non-lookaside free() routines to verify this constraint. 
+**
+** All of this is no-op for a production build.  It only comes into
+** play when the SQLITE_MEMDEBUG compile-time option is used.
+*/
+#ifdef SQLITE_MEMDEBUG
+  void sqlite3MemdebugSetType(void*,u8);
+  int sqlite3MemdebugHasType(void*,u8);
+#else
+# define sqlite3MemdebugSetType(X,Y)  /* no-op */
+# define sqlite3MemdebugHasType(X,Y)  1
 #endif
+#define MEMTYPE_HEAP     0x01    /* General heap allocations */
+#define MEMTYPE_DB       0x02    /* Associated with a database connection */
+#define MEMTYPE_SCRATCH  0x04    /* Scratch allocations */
+#define MEMTYPE_PCACHE   0x08    /* Page cache allocations */
+
+#endif /* _SQLITEINT_H_ */