xref: /sqlite-3.40.0/src/mem2.c (revision 04f1b691)
14c3645c6Sdrh /*
24c3645c6Sdrh ** 2007 August 15
34c3645c6Sdrh **
44c3645c6Sdrh ** The author disclaims copyright to this source code.  In place of
54c3645c6Sdrh ** a legal notice, here is a blessing:
64c3645c6Sdrh **
74c3645c6Sdrh **    May you do good and not evil.
84c3645c6Sdrh **    May you find forgiveness for yourself and forgive others.
94c3645c6Sdrh **    May you share freely, never taking more than you give.
104c3645c6Sdrh **
114c3645c6Sdrh *************************************************************************
124c3645c6Sdrh **
13fec00eabSdrh ** This file contains low-level memory allocation drivers for when
14fec00eabSdrh ** SQLite will use the standard C-library malloc/realloc/free interface
15fec00eabSdrh ** to obtain the memory it needs while adding lots of additional debugging
16fec00eabSdrh ** information to each allocation in order to help detect and fix memory
17fec00eabSdrh ** leaks and memory usage errors.
18fec00eabSdrh **
19fec00eabSdrh ** This file contains implementations of the low-level memory allocation
20fec00eabSdrh ** routines specified in the sqlite3_mem_methods object.
214c3645c6Sdrh */
220d18020bSdrh #include "sqliteInt.h"
234c3645c6Sdrh 
244c3645c6Sdrh /*
254c3645c6Sdrh ** This version of the memory allocator is used only if the
260d18020bSdrh ** SQLITE_MEMDEBUG macro is defined
274c3645c6Sdrh */
280d18020bSdrh #ifdef SQLITE_MEMDEBUG
294c3645c6Sdrh 
304c3645c6Sdrh /*
314c3645c6Sdrh ** The backtrace functionality is only available with GLIBC
324c3645c6Sdrh */
334c3645c6Sdrh #ifdef __GLIBC__
344c3645c6Sdrh   extern int backtrace(void**,int);
354c3645c6Sdrh   extern void backtrace_symbols_fd(void*const*,int,int);
364c3645c6Sdrh #else
3744a376f6Sdanielk1977 # define backtrace(A,B) 1
384c3645c6Sdrh # define backtrace_symbols_fd(A,B,C)
394c3645c6Sdrh #endif
400d18020bSdrh #include <stdio.h>
414c3645c6Sdrh 
424c3645c6Sdrh /*
434c3645c6Sdrh ** Each memory allocation looks like this:
444c3645c6Sdrh **
454a50aac5Sdrh **  ------------------------------------------------------------------------
464a50aac5Sdrh **  | Title |  backtrace pointers |  MemBlockHdr |  allocation |  EndGuard |
474a50aac5Sdrh **  ------------------------------------------------------------------------
484c3645c6Sdrh **
494c3645c6Sdrh ** The application code sees only a pointer to the allocation.  We have
504c3645c6Sdrh ** to back up from the allocation pointer to find the MemBlockHdr.  The
514c3645c6Sdrh ** MemBlockHdr tells us the size of the allocation and the number of
524c3645c6Sdrh ** backtrace pointers.  There is also a guard word at the end of the
534c3645c6Sdrh ** MemBlockHdr.
544c3645c6Sdrh */
554c3645c6Sdrh struct MemBlockHdr {
56fab69597Sdrh   i64 iSize;                          /* Size of this allocation */
574c3645c6Sdrh   struct MemBlockHdr *pNext, *pPrev;  /* Linked list of all unfreed memory */
58153c62c4Sdrh   char nBacktrace;                    /* Number of backtraces on this alloc */
59153c62c4Sdrh   char nBacktraceSlots;               /* Available backtrace slots */
60107b56e8Sdrh   u8 nTitle;                          /* Bytes of title; includes '\0' */
61107b56e8Sdrh   u8 eType;                           /* Allocation type code */
62153c62c4Sdrh   int iForeGuard;                     /* Guard word for sanity */
634c3645c6Sdrh };
644c3645c6Sdrh 
654c3645c6Sdrh /*
664c3645c6Sdrh ** Guard words
674c3645c6Sdrh */
684c3645c6Sdrh #define FOREGUARD 0x80F5E153
694c3645c6Sdrh #define REARGUARD 0xE4676B53
704c3645c6Sdrh 
714c3645c6Sdrh /*
72d2bb3278Sdrh ** Number of malloc size increments to track.
73d2bb3278Sdrh */
749c7a60dfSdrh #define NCSIZE  1000
75d2bb3278Sdrh 
76d2bb3278Sdrh /*
770e6f1546Sdrh ** All of the static variables used by this module are collected
780e6f1546Sdrh ** into a single structure named "mem".  This is to keep the
790e6f1546Sdrh ** static variables organized and to reduce namespace pollution
800e6f1546Sdrh ** when this module is combined with other in the amalgamation.
810e6f1546Sdrh */
820e6f1546Sdrh static struct {
830e6f1546Sdrh 
840e6f1546Sdrh   /*
850e6f1546Sdrh   ** Mutex to control access to the memory allocation subsystem.
860e6f1546Sdrh   */
870e6f1546Sdrh   sqlite3_mutex *mutex;
880e6f1546Sdrh 
890e6f1546Sdrh   /*
904c3645c6Sdrh   ** Head and tail of a linked list of all outstanding allocations
914c3645c6Sdrh   */
920e6f1546Sdrh   struct MemBlockHdr *pFirst;
930e6f1546Sdrh   struct MemBlockHdr *pLast;
944c3645c6Sdrh 
954c3645c6Sdrh   /*
964c3645c6Sdrh   ** The number of levels of backtrace to save in new allocations.
974c3645c6Sdrh   */
980e6f1546Sdrh   int nBacktrace;
996f332c18Sdanielk1977   void (*xBacktrace)(int, int, void **);
1000e6f1546Sdrh 
1010e6f1546Sdrh   /*
1024a50aac5Sdrh   ** Title text to insert in front of each block
1034a50aac5Sdrh   */
1044a50aac5Sdrh   int nTitle;        /* Bytes of zTitle to save.  Includes '\0' and padding */
1054a50aac5Sdrh   char zTitle[100];  /* The title text */
1064a50aac5Sdrh 
1074a50aac5Sdrh   /*
108d677b3d6Sdrh   ** sqlite3MallocDisallow() increments the following counter.
109d677b3d6Sdrh   ** sqlite3MallocAllow() decrements it.
110d677b3d6Sdrh   */
111d677b3d6Sdrh   int disallow; /* Do not allow memory allocation */
112d677b3d6Sdrh 
113d2bb3278Sdrh   /*
114d2bb3278Sdrh   ** Gather statistics on the sizes of memory allocations.
1152abcd58fSdrh   ** nAlloc[i] is the number of allocation attempts of i*8
116d2bb3278Sdrh   ** bytes.  i==NCSIZE is the number of allocation attempts for
1179c7a60dfSdrh   ** sizes more than NCSIZE*8 bytes.
118d2bb3278Sdrh   */
1192abcd58fSdrh   int nAlloc[NCSIZE];      /* Total number of allocations */
1202abcd58fSdrh   int nCurrent[NCSIZE];    /* Current number of allocations */
1212abcd58fSdrh   int mxCurrent[NCSIZE];   /* Highwater mark for nCurrent */
1220e6f1546Sdrh 
123153c62c4Sdrh } mem;
1240e6f1546Sdrh 
1252abcd58fSdrh 
1262abcd58fSdrh /*
1272abcd58fSdrh ** Adjust memory usage statistics
1282abcd58fSdrh */
adjustStats(int iSize,int increment)1292abcd58fSdrh static void adjustStats(int iSize, int increment){
130bc73971dSdanielk1977   int i = ROUND8(iSize)/8;
1312abcd58fSdrh   if( i>NCSIZE-1 ){
1322abcd58fSdrh     i = NCSIZE - 1;
1332abcd58fSdrh   }
1342abcd58fSdrh   if( increment>0 ){
1352abcd58fSdrh     mem.nAlloc[i]++;
1362abcd58fSdrh     mem.nCurrent[i]++;
1372abcd58fSdrh     if( mem.nCurrent[i]>mem.mxCurrent[i] ){
1382abcd58fSdrh       mem.mxCurrent[i] = mem.nCurrent[i];
1392abcd58fSdrh     }
1402abcd58fSdrh   }else{
1412abcd58fSdrh     mem.nCurrent[i]--;
1422abcd58fSdrh     assert( mem.nCurrent[i]>=0 );
1432abcd58fSdrh   }
1442abcd58fSdrh }
1452abcd58fSdrh 
1464c3645c6Sdrh /*
1474c3645c6Sdrh ** Given an allocation, find the MemBlockHdr for that allocation.
1484c3645c6Sdrh **
1494c3645c6Sdrh ** This routine checks the guards at either end of the allocation and
1504c3645c6Sdrh ** if they are incorrect it asserts.
1514c3645c6Sdrh */
sqlite3MemsysGetHeader(const void * pAllocation)152*04f1b691Smistachkin static struct MemBlockHdr *sqlite3MemsysGetHeader(const void *pAllocation){
1534c3645c6Sdrh   struct MemBlockHdr *p;
154153c62c4Sdrh   int *pInt;
155ce98bba2Sdanielk1977   u8 *pU8;
156ce98bba2Sdanielk1977   int nReserve;
1574c3645c6Sdrh 
1584c3645c6Sdrh   p = (struct MemBlockHdr*)pAllocation;
1594c3645c6Sdrh   p--;
160902b9ee4Sdrh   assert( p->iForeGuard==(int)FOREGUARD );
161bc73971dSdanielk1977   nReserve = ROUND8(p->iSize);
162153c62c4Sdrh   pInt = (int*)pAllocation;
163ce98bba2Sdanielk1977   pU8 = (u8*)pAllocation;
164902b9ee4Sdrh   assert( pInt[nReserve/sizeof(int)]==(int)REARGUARD );
165d20010c7Sshane   /* This checks any of the "extra" bytes allocated due
166d20010c7Sshane   ** to rounding up to an 8 byte boundary to ensure
167d20010c7Sshane   ** they haven't been overwritten.
168d20010c7Sshane   */
169d20010c7Sshane   while( nReserve-- > p->iSize ) assert( pU8[nReserve]==0x65 );
1704c3645c6Sdrh   return p;
1714c3645c6Sdrh }
1724c3645c6Sdrh 
1734c3645c6Sdrh /*
174a7a8e14bSdanielk1977 ** Return the number of bytes currently allocated at address p.
175a7a8e14bSdanielk1977 */
sqlite3MemSize(void * p)176fec00eabSdrh static int sqlite3MemSize(void *p){
177a7a8e14bSdanielk1977   struct MemBlockHdr *pHdr;
178a7a8e14bSdanielk1977   if( !p ){
179a7a8e14bSdanielk1977     return 0;
180a7a8e14bSdanielk1977   }
181a7a8e14bSdanielk1977   pHdr = sqlite3MemsysGetHeader(p);
182f6418891Smistachkin   return (int)pHdr->iSize;
183a7a8e14bSdanielk1977 }
184a7a8e14bSdanielk1977 
185a7a8e14bSdanielk1977 /*
186fec00eabSdrh ** Initialize the memory allocation subsystem.
18740257ffdSdrh */
sqlite3MemInit(void * NotUsed)188fec00eabSdrh static int sqlite3MemInit(void *NotUsed){
189902b9ee4Sdrh   UNUSED_PARAMETER(NotUsed);
190d20010c7Sshane   assert( (sizeof(struct MemBlockHdr)&7) == 0 );
191075c23afSdanielk1977   if( !sqlite3GlobalConfig.bMemstat ){
19265bbf29eSdrh     /* If memory status is enabled, then the malloc.c wrapper will already
19365bbf29eSdrh     ** hold the STATIC_MEM mutex when the routines here are invoked. */
19459f8c08eSdanielk1977     mem.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
19565bbf29eSdrh   }
19640257ffdSdrh   return SQLITE_OK;
19740257ffdSdrh }
19840257ffdSdrh 
19940257ffdSdrh /*
200fec00eabSdrh ** Deinitialize the memory allocation subsystem.
201fec00eabSdrh */
sqlite3MemShutdown(void * NotUsed)202fec00eabSdrh static void sqlite3MemShutdown(void *NotUsed){
203902b9ee4Sdrh   UNUSED_PARAMETER(NotUsed);
204fec00eabSdrh   mem.mutex = 0;
205fec00eabSdrh }
206fec00eabSdrh 
207fec00eabSdrh /*
208fec00eabSdrh ** Round up a request size to the next valid allocation size.
209fec00eabSdrh */
sqlite3MemRoundup(int n)210fec00eabSdrh static int sqlite3MemRoundup(int n){
211bc73971dSdanielk1977   return ROUND8(n);
212fec00eabSdrh }
213fec00eabSdrh 
214fec00eabSdrh /*
21510f864e8Sdrh ** Fill a buffer with pseudo-random bytes.  This is used to preset
21610f864e8Sdrh ** the content of a new memory allocation to unpredictable values and
21710f864e8Sdrh ** to clear the content of a freed allocation to unpredictable values.
21810f864e8Sdrh */
randomFill(char * pBuf,int nByte)21910f864e8Sdrh static void randomFill(char *pBuf, int nByte){
22010f864e8Sdrh   unsigned int x, y, r;
22110f864e8Sdrh   x = SQLITE_PTR_TO_INT(pBuf);
22210f864e8Sdrh   y = nByte | 1;
22310f864e8Sdrh   while( nByte >= 4 ){
224f6418891Smistachkin     x = (x>>1) ^ (-(int)(x&1) & 0xd0000001);
22510f864e8Sdrh     y = y*1103515245 + 12345;
22610f864e8Sdrh     r = x ^ y;
22710f864e8Sdrh     *(int*)pBuf = r;
22810f864e8Sdrh     pBuf += 4;
22910f864e8Sdrh     nByte -= 4;
23010f864e8Sdrh   }
23110f864e8Sdrh   while( nByte-- > 0 ){
232f6418891Smistachkin     x = (x>>1) ^ (-(int)(x&1) & 0xd0000001);
23310f864e8Sdrh     y = y*1103515245 + 12345;
23410f864e8Sdrh     r = x ^ y;
23510f864e8Sdrh     *(pBuf++) = r & 0xff;
23610f864e8Sdrh   }
23710f864e8Sdrh }
23810f864e8Sdrh 
23910f864e8Sdrh /*
2400e6f1546Sdrh ** Allocate nByte bytes of memory.
2414c3645c6Sdrh */
sqlite3MemMalloc(int nByte)242fec00eabSdrh static void *sqlite3MemMalloc(int nByte){
2434c3645c6Sdrh   struct MemBlockHdr *pHdr;
2444c3645c6Sdrh   void **pBt;
2454a50aac5Sdrh   char *z;
246153c62c4Sdrh   int *pInt;
247ca0c8971Sdanielk1977   void *p = 0;
248153c62c4Sdrh   int totalSize;
249ce98bba2Sdanielk1977   int nReserve;
250fec00eabSdrh   sqlite3_mutex_enter(mem.mutex);
251d677b3d6Sdrh   assert( mem.disallow==0 );
252bc73971dSdanielk1977   nReserve = ROUND8(nByte);
253ce98bba2Sdanielk1977   totalSize = nReserve + sizeof(*pHdr) + sizeof(int) +
2544a50aac5Sdrh                mem.nBacktrace*sizeof(void*) + mem.nTitle;
2554c3645c6Sdrh   p = malloc(totalSize);
2564c3645c6Sdrh   if( p ){
2574a50aac5Sdrh     z = p;
2584a50aac5Sdrh     pBt = (void**)&z[mem.nTitle];
2590e6f1546Sdrh     pHdr = (struct MemBlockHdr*)&pBt[mem.nBacktrace];
2604c3645c6Sdrh     pHdr->pNext = 0;
2610e6f1546Sdrh     pHdr->pPrev = mem.pLast;
2620e6f1546Sdrh     if( mem.pLast ){
2630e6f1546Sdrh       mem.pLast->pNext = pHdr;
2644c3645c6Sdrh     }else{
2650e6f1546Sdrh       mem.pFirst = pHdr;
2664c3645c6Sdrh     }
2670e6f1546Sdrh     mem.pLast = pHdr;
2684c3645c6Sdrh     pHdr->iForeGuard = FOREGUARD;
269107b56e8Sdrh     pHdr->eType = MEMTYPE_HEAP;
2700e6f1546Sdrh     pHdr->nBacktraceSlots = mem.nBacktrace;
2714a50aac5Sdrh     pHdr->nTitle = mem.nTitle;
2720e6f1546Sdrh     if( mem.nBacktrace ){
2732f999a67Sdrh       void *aAddr[40];
2740e6f1546Sdrh       pHdr->nBacktrace = backtrace(aAddr, mem.nBacktrace+1)-1;
2752f999a67Sdrh       memcpy(pBt, &aAddr[1], pHdr->nBacktrace*sizeof(void*));
2766ab3a2ecSdanielk1977       assert(pBt[0]);
2776f332c18Sdanielk1977       if( mem.xBacktrace ){
2786f332c18Sdanielk1977         mem.xBacktrace(nByte, pHdr->nBacktrace-1, &aAddr[1]);
2796f332c18Sdanielk1977       }
2804c3645c6Sdrh     }else{
2814c3645c6Sdrh       pHdr->nBacktrace = 0;
2824c3645c6Sdrh     }
2834a50aac5Sdrh     if( mem.nTitle ){
2844a50aac5Sdrh       memcpy(z, mem.zTitle, mem.nTitle);
2854a50aac5Sdrh     }
2864c3645c6Sdrh     pHdr->iSize = nByte;
2872abcd58fSdrh     adjustStats(nByte, +1);
288153c62c4Sdrh     pInt = (int*)&pHdr[1];
289ce98bba2Sdanielk1977     pInt[nReserve/sizeof(int)] = REARGUARD;
29010f864e8Sdrh     randomFill((char*)pInt, nByte);
29110f864e8Sdrh     memset(((char*)pInt)+nByte, 0x65, nReserve-nByte);
2924c3645c6Sdrh     p = (void*)pInt;
2934c3645c6Sdrh   }
2940e6f1546Sdrh   sqlite3_mutex_leave(mem.mutex);
2954c3645c6Sdrh   return p;
2964c3645c6Sdrh }
2974c3645c6Sdrh 
2984c3645c6Sdrh /*
2994c3645c6Sdrh ** Free memory.
3004c3645c6Sdrh */
sqlite3MemFree(void * pPrior)301fec00eabSdrh static void sqlite3MemFree(void *pPrior){
3024c3645c6Sdrh   struct MemBlockHdr *pHdr;
3034c3645c6Sdrh   void **pBt;
3044a50aac5Sdrh   char *z;
3053b4aae56Sdan   assert( sqlite3GlobalConfig.bMemstat || sqlite3GlobalConfig.bCoreMutex==0
3063b4aae56Sdan        || mem.mutex!=0 );
3074c3645c6Sdrh   pHdr = sqlite3MemsysGetHeader(pPrior);
3084c3645c6Sdrh   pBt = (void**)pHdr;
3094c3645c6Sdrh   pBt -= pHdr->nBacktraceSlots;
3106bdec4afSdrh   sqlite3_mutex_enter(mem.mutex);
3114c3645c6Sdrh   if( pHdr->pPrev ){
3124c3645c6Sdrh     assert( pHdr->pPrev->pNext==pHdr );
3134c3645c6Sdrh     pHdr->pPrev->pNext = pHdr->pNext;
3144c3645c6Sdrh   }else{
3150e6f1546Sdrh     assert( mem.pFirst==pHdr );
3160e6f1546Sdrh     mem.pFirst = pHdr->pNext;
3174c3645c6Sdrh   }
3184c3645c6Sdrh   if( pHdr->pNext ){
3194c3645c6Sdrh     assert( pHdr->pNext->pPrev==pHdr );
3204c3645c6Sdrh     pHdr->pNext->pPrev = pHdr->pPrev;
3214c3645c6Sdrh   }else{
3220e6f1546Sdrh     assert( mem.pLast==pHdr );
3230e6f1546Sdrh     mem.pLast = pHdr->pPrev;
3244c3645c6Sdrh   }
3254a50aac5Sdrh   z = (char*)pBt;
3264a50aac5Sdrh   z -= pHdr->nTitle;
327f6418891Smistachkin   adjustStats((int)pHdr->iSize, -1);
32810f864e8Sdrh   randomFill(z, sizeof(void*)*pHdr->nBacktraceSlots + sizeof(*pHdr) +
329f6418891Smistachkin                 (int)pHdr->iSize + sizeof(int) + pHdr->nTitle);
3304a50aac5Sdrh   free(z);
3310e6f1546Sdrh   sqlite3_mutex_leave(mem.mutex);
3324c3645c6Sdrh }
3334c3645c6Sdrh 
3344c3645c6Sdrh /*
3354c3645c6Sdrh ** Change the size of an existing memory allocation.
3364c3645c6Sdrh **
3374c3645c6Sdrh ** For this debugging implementation, we *always* make a copy of the
3384c3645c6Sdrh ** allocation into a new place in memory.  In this way, if the
3394c3645c6Sdrh ** higher level code is using pointer to the old allocation, it is
3404c3645c6Sdrh ** much more likely to break and we are much more liking to find
3414c3645c6Sdrh ** the error.
3424c3645c6Sdrh */
sqlite3MemRealloc(void * pPrior,int nByte)343fec00eabSdrh static void *sqlite3MemRealloc(void *pPrior, int nByte){
3444c3645c6Sdrh   struct MemBlockHdr *pOldHdr;
3454c3645c6Sdrh   void *pNew;
346d677b3d6Sdrh   assert( mem.disallow==0 );
3479f129f46Sdrh   assert( (nByte & 7)==0 );     /* EV: R-46199-30249 */
3484c3645c6Sdrh   pOldHdr = sqlite3MemsysGetHeader(pPrior);
349fec00eabSdrh   pNew = sqlite3MemMalloc(nByte);
3504c3645c6Sdrh   if( pNew ){
3513fb4b6dfSmistachkin     memcpy(pNew, pPrior, (int)(nByte<pOldHdr->iSize ? nByte : pOldHdr->iSize));
3524c3645c6Sdrh     if( nByte>pOldHdr->iSize ){
353f6418891Smistachkin       randomFill(&((char*)pNew)[pOldHdr->iSize], nByte - (int)pOldHdr->iSize);
3544c3645c6Sdrh     }
355fec00eabSdrh     sqlite3MemFree(pPrior);
3564c3645c6Sdrh   }
3574c3645c6Sdrh   return pNew;
3584c3645c6Sdrh }
3594c3645c6Sdrh 
360d1370b6dSdrh /*
361d1370b6dSdrh ** Populate the low-level memory allocation function pointers in
362d1370b6dSdrh ** sqlite3GlobalConfig.m with pointers to the routines in this file.
363d1370b6dSdrh */
sqlite3MemSetDefault(void)364d1370b6dSdrh void sqlite3MemSetDefault(void){
365fec00eabSdrh   static const sqlite3_mem_methods defaultMethods = {
366fec00eabSdrh      sqlite3MemMalloc,
367fec00eabSdrh      sqlite3MemFree,
368fec00eabSdrh      sqlite3MemRealloc,
369fec00eabSdrh      sqlite3MemSize,
370fec00eabSdrh      sqlite3MemRoundup,
371fec00eabSdrh      sqlite3MemInit,
372fec00eabSdrh      sqlite3MemShutdown,
373fec00eabSdrh      0
374fec00eabSdrh   };
375d1370b6dSdrh   sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods);
376fec00eabSdrh }
377fec00eabSdrh 
3784c3645c6Sdrh /*
379107b56e8Sdrh ** Set the "type" of an allocation.
380107b56e8Sdrh */
sqlite3MemdebugSetType(void * p,u8 eType)381107b56e8Sdrh void sqlite3MemdebugSetType(void *p, u8 eType){
3829a23d26cSdan   if( p && sqlite3GlobalConfig.m.xFree==sqlite3MemFree ){
383107b56e8Sdrh     struct MemBlockHdr *pHdr;
384107b56e8Sdrh     pHdr = sqlite3MemsysGetHeader(p);
385107b56e8Sdrh     assert( pHdr->iForeGuard==FOREGUARD );
386107b56e8Sdrh     pHdr->eType = eType;
387107b56e8Sdrh   }
388107b56e8Sdrh }
389107b56e8Sdrh 
390107b56e8Sdrh /*
391107b56e8Sdrh ** Return TRUE if the mask of type in eType matches the type of the
392107b56e8Sdrh ** allocation p.  Also return true if p==NULL.
393107b56e8Sdrh **
394107b56e8Sdrh ** This routine is designed for use within an assert() statement, to
395107b56e8Sdrh ** verify the type of an allocation.  For example:
396107b56e8Sdrh **
397d231aa3aSdrh **     assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
398107b56e8Sdrh */
sqlite3MemdebugHasType(const void * p,u8 eType)39977978a64Smistachkin int sqlite3MemdebugHasType(const void *p, u8 eType){
400107b56e8Sdrh   int rc = 1;
4019a23d26cSdan   if( p && sqlite3GlobalConfig.m.xFree==sqlite3MemFree ){
402107b56e8Sdrh     struct MemBlockHdr *pHdr;
403107b56e8Sdrh     pHdr = sqlite3MemsysGetHeader(p);
404107b56e8Sdrh     assert( pHdr->iForeGuard==FOREGUARD );         /* Allocation is valid */
405107b56e8Sdrh     if( (pHdr->eType&eType)==0 ){
406107b56e8Sdrh       rc = 0;
407107b56e8Sdrh     }
408107b56e8Sdrh   }
409107b56e8Sdrh   return rc;
410107b56e8Sdrh }
411107b56e8Sdrh 
412174b9a16Sdrh /*
413174b9a16Sdrh ** Return TRUE if the mask of type in eType matches no bits of the type of the
414174b9a16Sdrh ** allocation p.  Also return true if p==NULL.
415174b9a16Sdrh **
416174b9a16Sdrh ** This routine is designed for use within an assert() statement, to
417174b9a16Sdrh ** verify the type of an allocation.  For example:
418174b9a16Sdrh **
419d231aa3aSdrh **     assert( sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
420174b9a16Sdrh */
sqlite3MemdebugNoType(const void * p,u8 eType)42177978a64Smistachkin int sqlite3MemdebugNoType(const void *p, u8 eType){
422174b9a16Sdrh   int rc = 1;
4239a23d26cSdan   if( p && sqlite3GlobalConfig.m.xFree==sqlite3MemFree ){
424174b9a16Sdrh     struct MemBlockHdr *pHdr;
425174b9a16Sdrh     pHdr = sqlite3MemsysGetHeader(p);
426174b9a16Sdrh     assert( pHdr->iForeGuard==FOREGUARD );         /* Allocation is valid */
427174b9a16Sdrh     if( (pHdr->eType&eType)!=0 ){
428174b9a16Sdrh       rc = 0;
429174b9a16Sdrh     }
430174b9a16Sdrh   }
431174b9a16Sdrh   return rc;
432174b9a16Sdrh }
433107b56e8Sdrh 
434107b56e8Sdrh /*
4354c3645c6Sdrh ** Set the number of backtrace levels kept for each allocation.
4366d2ab0e4Sdanielk1977 ** A value of zero turns off backtracing.  The number is always rounded
4374c3645c6Sdrh ** up to a multiple of 2.
4384c3645c6Sdrh */
sqlite3MemdebugBacktrace(int depth)43949e4fd71Sdrh void sqlite3MemdebugBacktrace(int depth){
4404c3645c6Sdrh   if( depth<0 ){ depth = 0; }
4414c3645c6Sdrh   if( depth>20 ){ depth = 20; }
4422f999a67Sdrh   depth = (depth+1)&0xfe;
4430e6f1546Sdrh   mem.nBacktrace = depth;
4444c3645c6Sdrh }
4454c3645c6Sdrh 
sqlite3MemdebugBacktraceCallback(void (* xBacktrace)(int,int,void **))4466f332c18Sdanielk1977 void sqlite3MemdebugBacktraceCallback(void (*xBacktrace)(int, int, void **)){
4476f332c18Sdanielk1977   mem.xBacktrace = xBacktrace;
4486f332c18Sdanielk1977 }
4496f332c18Sdanielk1977 
4504c3645c6Sdrh /*
4514a50aac5Sdrh ** Set the title string for subsequent allocations.
4524a50aac5Sdrh */
sqlite3MemdebugSettitle(const char * zTitle)45349e4fd71Sdrh void sqlite3MemdebugSettitle(const char *zTitle){
454ea678832Sdrh   unsigned int n = sqlite3Strlen30(zTitle) + 1;
455fec00eabSdrh   sqlite3_mutex_enter(mem.mutex);
4564a50aac5Sdrh   if( n>=sizeof(mem.zTitle) ) n = sizeof(mem.zTitle)-1;
4574a50aac5Sdrh   memcpy(mem.zTitle, zTitle, n);
4584a50aac5Sdrh   mem.zTitle[n] = 0;
459bc73971dSdanielk1977   mem.nTitle = ROUND8(n);
4604a50aac5Sdrh   sqlite3_mutex_leave(mem.mutex);
4614a50aac5Sdrh }
4624a50aac5Sdrh 
sqlite3MemdebugSync()463dbdc4d49Sdanielk1977 void sqlite3MemdebugSync(){
464dbdc4d49Sdanielk1977   struct MemBlockHdr *pHdr;
465dbdc4d49Sdanielk1977   for(pHdr=mem.pFirst; pHdr; pHdr=pHdr->pNext){
466dbdc4d49Sdanielk1977     void **pBt = (void**)pHdr;
467dbdc4d49Sdanielk1977     pBt -= pHdr->nBacktraceSlots;
468f6418891Smistachkin     mem.xBacktrace((int)pHdr->iSize, pHdr->nBacktrace-1, &pBt[1]);
469dbdc4d49Sdanielk1977   }
470dbdc4d49Sdanielk1977 }
471dbdc4d49Sdanielk1977 
4724a50aac5Sdrh /*
4734c3645c6Sdrh ** Open the file indicated and write a log of all unfreed memory
4744c3645c6Sdrh ** allocations into that log.
4754c3645c6Sdrh */
sqlite3MemdebugDump(const char * zFilename)47649e4fd71Sdrh void sqlite3MemdebugDump(const char *zFilename){
4774c3645c6Sdrh   FILE *out;
4784c3645c6Sdrh   struct MemBlockHdr *pHdr;
4794c3645c6Sdrh   void **pBt;
480d2bb3278Sdrh   int i;
4814c3645c6Sdrh   out = fopen(zFilename, "w");
4824c3645c6Sdrh   if( out==0 ){
4834c3645c6Sdrh     fprintf(stderr, "** Unable to output memory debug output log: %s **\n",
4844c3645c6Sdrh                     zFilename);
4854c3645c6Sdrh     return;
4864c3645c6Sdrh   }
4870e6f1546Sdrh   for(pHdr=mem.pFirst; pHdr; pHdr=pHdr->pNext){
4884a50aac5Sdrh     char *z = (char*)pHdr;
4894a50aac5Sdrh     z -= pHdr->nBacktraceSlots*sizeof(void*) + pHdr->nTitle;
490fab69597Sdrh     fprintf(out, "**** %lld bytes at %p from %s ****\n",
491d5499d64Sdrh             pHdr->iSize, &pHdr[1], pHdr->nTitle ? z : "???");
4924c3645c6Sdrh     if( pHdr->nBacktrace ){
4934c3645c6Sdrh       fflush(out);
4944c3645c6Sdrh       pBt = (void**)pHdr;
4954c3645c6Sdrh       pBt -= pHdr->nBacktraceSlots;
4964c3645c6Sdrh       backtrace_symbols_fd(pBt, pHdr->nBacktrace, fileno(out));
4974c3645c6Sdrh       fprintf(out, "\n");
4984c3645c6Sdrh     }
4994c3645c6Sdrh   }
500d2bb3278Sdrh   fprintf(out, "COUNTS:\n");
501d2bb3278Sdrh   for(i=0; i<NCSIZE-1; i++){
5022abcd58fSdrh     if( mem.nAlloc[i] ){
5032abcd58fSdrh       fprintf(out, "   %5d: %10d %10d %10d\n",
5042abcd58fSdrh             i*8, mem.nAlloc[i], mem.nCurrent[i], mem.mxCurrent[i]);
505d2bb3278Sdrh     }
506d2bb3278Sdrh   }
5072abcd58fSdrh   if( mem.nAlloc[NCSIZE-1] ){
5082abcd58fSdrh     fprintf(out, "   %5d: %10d %10d %10d\n",
5092abcd58fSdrh              NCSIZE*8-8, mem.nAlloc[NCSIZE-1],
5102abcd58fSdrh              mem.nCurrent[NCSIZE-1], mem.mxCurrent[NCSIZE-1]);
511d2bb3278Sdrh   }
5124c3645c6Sdrh   fclose(out);
5134c3645c6Sdrh }
5144c3645c6Sdrh 
515a7a8e14bSdanielk1977 /*
516fec00eabSdrh ** Return the number of times sqlite3MemMalloc() has been called.
517a7a8e14bSdanielk1977 */
sqlite3MemdebugMallocCount()51849e4fd71Sdrh int sqlite3MemdebugMallocCount(){
519a7a8e14bSdanielk1977   int i;
520a7a8e14bSdanielk1977   int nTotal = 0;
521a7a8e14bSdanielk1977   for(i=0; i<NCSIZE; i++){
5222abcd58fSdrh     nTotal += mem.nAlloc[i];
523a7a8e14bSdanielk1977   }
524a7a8e14bSdanielk1977   return nTotal;
525a7a8e14bSdanielk1977 }
526a7a8e14bSdanielk1977 
527d677b3d6Sdrh 
5280d18020bSdrh #endif /* SQLITE_MEMDEBUG */
529