| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 ** 2007 August 15 | |
| 3 ** | |
| 4 ** The author disclaims copyright to this source code. In place of | |
| 5 ** a legal notice, here is a blessing: | |
| 6 ** | |
| 7 ** May you do good and not evil. | |
| 8 ** May you find forgiveness for yourself and forgive others. | |
| 9 ** May you share freely, never taking more than you give. | |
| 10 ** | |
| 11 ************************************************************************* | |
| 12 ** | |
| 13 ** This file contains low-level memory allocation drivers for when | |
| 14 ** SQLite will use the standard C-library malloc/realloc/free interface | |
| 15 ** to obtain the memory it needs while adding lots of additional debugging | |
| 16 ** information to each allocation in order to help detect and fix memory | |
| 17 ** leaks and memory usage errors. | |
| 18 ** | |
| 19 ** This file contains implementations of the low-level memory allocation | |
| 20 ** routines specified in the sqlite3_mem_methods object. | |
| 21 ** | |
| 22 ** $Id: mem2.c,v 1.45 2009/03/23 04:33:33 danielk1977 Exp $ | |
| 23 */ | |
| 24 #include "sqliteInt.h" | |
| 25 | |
| 26 /* | |
| 27 ** This version of the memory allocator is used only if the | |
| 28 ** SQLITE_MEMDEBUG macro is defined | |
| 29 */ | |
| 30 #ifdef SQLITE_MEMDEBUG | |
| 31 | |
| 32 /* | |
| 33 ** The backtrace functionality is only available with GLIBC | |
| 34 */ | |
| 35 #ifdef __GLIBC__ | |
| 36 extern int backtrace(void**,int); | |
| 37 extern void backtrace_symbols_fd(void*const*,int,int); | |
| 38 #else | |
| 39 # define backtrace(A,B) 1 | |
| 40 # define backtrace_symbols_fd(A,B,C) | |
| 41 #endif | |
| 42 #include <stdio.h> | |
| 43 | |
| 44 /* | |
| 45 ** Each memory allocation looks like this: | |
| 46 ** | |
| 47 ** ------------------------------------------------------------------------ | |
| 48 ** | Title | backtrace pointers | MemBlockHdr | allocation | EndGuard | | |
| 49 ** ------------------------------------------------------------------------ | |
| 50 ** | |
| 51 ** The application code sees only a pointer to the allocation. We have | |
| 52 ** to back up from the allocation pointer to find the MemBlockHdr. The | |
| 53 ** MemBlockHdr tells us the size of the allocation and the number of | |
| 54 ** backtrace pointers. There is also a guard word at the end of the | |
| 55 ** MemBlockHdr. | |
| 56 */ | |
| 57 struct MemBlockHdr { | |
| 58 i64 iSize; /* Size of this allocation */ | |
| 59 struct MemBlockHdr *pNext, *pPrev; /* Linked list of all unfreed memory */ | |
| 60 char nBacktrace; /* Number of backtraces on this alloc */ | |
| 61 char nBacktraceSlots; /* Available backtrace slots */ | |
| 62 short nTitle; /* Bytes of title; includes '\0' */ | |
| 63 int iForeGuard; /* Guard word for sanity */ | |
| 64 }; | |
| 65 | |
| 66 /* | |
| 67 ** Guard words | |
| 68 */ | |
| 69 #define FOREGUARD 0x80F5E153 | |
| 70 #define REARGUARD 0xE4676B53 | |
| 71 | |
| 72 /* | |
| 73 ** Number of malloc size increments to track. | |
| 74 */ | |
| 75 #define NCSIZE 1000 | |
| 76 | |
| 77 /* | |
| 78 ** All of the static variables used by this module are collected | |
| 79 ** into a single structure named "mem". This is to keep the | |
| 80 ** static variables organized and to reduce namespace pollution | |
| 81 ** when this module is combined with other in the amalgamation. | |
| 82 */ | |
| 83 static struct { | |
| 84 | |
| 85 /* | |
| 86 ** Mutex to control access to the memory allocation subsystem. | |
| 87 */ | |
| 88 sqlite3_mutex *mutex; | |
| 89 | |
| 90 /* | |
| 91 ** Head and tail of a linked list of all outstanding allocations | |
| 92 */ | |
| 93 struct MemBlockHdr *pFirst; | |
| 94 struct MemBlockHdr *pLast; | |
| 95 | |
| 96 /* | |
| 97 ** The number of levels of backtrace to save in new allocations. | |
| 98 */ | |
| 99 int nBacktrace; | |
| 100 void (*xBacktrace)(int, int, void **); | |
| 101 | |
| 102 /* | |
| 103 ** Title text to insert in front of each block | |
| 104 */ | |
| 105 int nTitle; /* Bytes of zTitle to save. Includes '\0' and padding */ | |
| 106 char zTitle[100]; /* The title text */ | |
| 107 | |
| 108 /* | |
| 109 ** sqlite3MallocDisallow() increments the following counter. | |
| 110 ** sqlite3MallocAllow() decrements it. | |
| 111 */ | |
| 112 int disallow; /* Do not allow memory allocation */ | |
| 113 | |
| 114 /* | |
| 115 ** Gather statistics on the sizes of memory allocations. | |
| 116 ** nAlloc[i] is the number of allocation attempts of i*8 | |
| 117 ** bytes. i==NCSIZE is the number of allocation attempts for | |
| 118 ** sizes more than NCSIZE*8 bytes. | |
| 119 */ | |
| 120 int nAlloc[NCSIZE]; /* Total number of allocations */ | |
| 121 int nCurrent[NCSIZE]; /* Current number of allocations */ | |
| 122 int mxCurrent[NCSIZE]; /* Highwater mark for nCurrent */ | |
| 123 | |
| 124 } mem; | |
| 125 | |
| 126 | |
| 127 /* | |
| 128 ** Adjust memory usage statistics | |
| 129 */ | |
| 130 static void adjustStats(int iSize, int increment){ | |
| 131 int i = ROUND8(iSize)/8; | |
| 132 if( i>NCSIZE-1 ){ | |
| 133 i = NCSIZE - 1; | |
| 134 } | |
| 135 if( increment>0 ){ | |
| 136 mem.nAlloc[i]++; | |
| 137 mem.nCurrent[i]++; | |
| 138 if( mem.nCurrent[i]>mem.mxCurrent[i] ){ | |
| 139 mem.mxCurrent[i] = mem.nCurrent[i]; | |
| 140 } | |
| 141 }else{ | |
| 142 mem.nCurrent[i]--; | |
| 143 assert( mem.nCurrent[i]>=0 ); | |
| 144 } | |
| 145 } | |
| 146 | |
| 147 /* | |
| 148 ** Given an allocation, find the MemBlockHdr for that allocation. | |
| 149 ** | |
| 150 ** This routine checks the guards at either end of the allocation and | |
| 151 ** if they are incorrect it asserts. | |
| 152 */ | |
| 153 static struct MemBlockHdr *sqlite3MemsysGetHeader(void *pAllocation){ | |
| 154 struct MemBlockHdr *p; | |
| 155 int *pInt; | |
| 156 u8 *pU8; | |
| 157 int nReserve; | |
| 158 | |
| 159 p = (struct MemBlockHdr*)pAllocation; | |
| 160 p--; | |
| 161 assert( p->iForeGuard==(int)FOREGUARD ); | |
| 162 nReserve = ROUND8(p->iSize); | |
| 163 pInt = (int*)pAllocation; | |
| 164 pU8 = (u8*)pAllocation; | |
| 165 assert( pInt[nReserve/sizeof(int)]==(int)REARGUARD ); | |
| 166 /* This checks any of the "extra" bytes allocated due | |
| 167 ** to rounding up to an 8 byte boundary to ensure | |
| 168 ** they haven't been overwritten. | |
| 169 */ | |
| 170 while( nReserve-- > p->iSize ) assert( pU8[nReserve]==0x65 ); | |
| 171 return p; | |
| 172 } | |
| 173 | |
| 174 /* | |
| 175 ** Return the number of bytes currently allocated at address p. | |
| 176 */ | |
| 177 static int sqlite3MemSize(void *p){ | |
| 178 struct MemBlockHdr *pHdr; | |
| 179 if( !p ){ | |
| 180 return 0; | |
| 181 } | |
| 182 pHdr = sqlite3MemsysGetHeader(p); | |
| 183 return pHdr->iSize; | |
| 184 } | |
| 185 | |
| 186 /* | |
| 187 ** Initialize the memory allocation subsystem. | |
| 188 */ | |
| 189 static int sqlite3MemInit(void *NotUsed){ | |
| 190 UNUSED_PARAMETER(NotUsed); | |
| 191 assert( (sizeof(struct MemBlockHdr)&7) == 0 ); | |
| 192 if( !sqlite3GlobalConfig.bMemstat ){ | |
| 193 /* If memory status is enabled, then the malloc.c wrapper will already | |
| 194 ** hold the STATIC_MEM mutex when the routines here are invoked. */ | |
| 195 mem.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); | |
| 196 } | |
| 197 return SQLITE_OK; | |
| 198 } | |
| 199 | |
| 200 /* | |
| 201 ** Deinitialize the memory allocation subsystem. | |
| 202 */ | |
| 203 static void sqlite3MemShutdown(void *NotUsed){ | |
| 204 UNUSED_PARAMETER(NotUsed); | |
| 205 mem.mutex = 0; | |
| 206 } | |
| 207 | |
| 208 /* | |
| 209 ** Round up a request size to the next valid allocation size. | |
| 210 */ | |
| 211 static int sqlite3MemRoundup(int n){ | |
| 212 return ROUND8(n); | |
| 213 } | |
| 214 | |
| 215 /* | |
| 216 ** Allocate nByte bytes of memory. | |
| 217 */ | |
| 218 static void *sqlite3MemMalloc(int nByte){ | |
| 219 struct MemBlockHdr *pHdr; | |
| 220 void **pBt; | |
| 221 char *z; | |
| 222 int *pInt; | |
| 223 void *p = 0; | |
| 224 int totalSize; | |
| 225 int nReserve; | |
| 226 sqlite3_mutex_enter(mem.mutex); | |
| 227 assert( mem.disallow==0 ); | |
| 228 nReserve = ROUND8(nByte); | |
| 229 totalSize = nReserve + sizeof(*pHdr) + sizeof(int) + | |
| 230 mem.nBacktrace*sizeof(void*) + mem.nTitle; | |
| 231 p = malloc(totalSize); | |
| 232 if( p ){ | |
| 233 z = p; | |
| 234 pBt = (void**)&z[mem.nTitle]; | |
| 235 pHdr = (struct MemBlockHdr*)&pBt[mem.nBacktrace]; | |
| 236 pHdr->pNext = 0; | |
| 237 pHdr->pPrev = mem.pLast; | |
| 238 if( mem.pLast ){ | |
| 239 mem.pLast->pNext = pHdr; | |
| 240 }else{ | |
| 241 mem.pFirst = pHdr; | |
| 242 } | |
| 243 mem.pLast = pHdr; | |
| 244 pHdr->iForeGuard = FOREGUARD; | |
| 245 pHdr->nBacktraceSlots = mem.nBacktrace; | |
| 246 pHdr->nTitle = mem.nTitle; | |
| 247 if( mem.nBacktrace ){ | |
| 248 void *aAddr[40]; | |
| 249 pHdr->nBacktrace = backtrace(aAddr, mem.nBacktrace+1)-1; | |
| 250 memcpy(pBt, &aAddr[1], pHdr->nBacktrace*sizeof(void*)); | |
| 251 assert(pBt[0]); | |
| 252 if( mem.xBacktrace ){ | |
| 253 mem.xBacktrace(nByte, pHdr->nBacktrace-1, &aAddr[1]); | |
| 254 } | |
| 255 }else{ | |
| 256 pHdr->nBacktrace = 0; | |
| 257 } | |
| 258 if( mem.nTitle ){ | |
| 259 memcpy(z, mem.zTitle, mem.nTitle); | |
| 260 } | |
| 261 pHdr->iSize = nByte; | |
| 262 adjustStats(nByte, +1); | |
| 263 pInt = (int*)&pHdr[1]; | |
| 264 pInt[nReserve/sizeof(int)] = REARGUARD; | |
| 265 memset(pInt, 0x65, nReserve); | |
| 266 p = (void*)pInt; | |
| 267 } | |
| 268 sqlite3_mutex_leave(mem.mutex); | |
| 269 return p; | |
| 270 } | |
| 271 | |
| 272 /* | |
| 273 ** Free memory. | |
| 274 */ | |
| 275 static void sqlite3MemFree(void *pPrior){ | |
| 276 struct MemBlockHdr *pHdr; | |
| 277 void **pBt; | |
| 278 char *z; | |
| 279 assert( sqlite3GlobalConfig.bMemstat || mem.mutex!=0 ); | |
| 280 pHdr = sqlite3MemsysGetHeader(pPrior); | |
| 281 pBt = (void**)pHdr; | |
| 282 pBt -= pHdr->nBacktraceSlots; | |
| 283 sqlite3_mutex_enter(mem.mutex); | |
| 284 if( pHdr->pPrev ){ | |
| 285 assert( pHdr->pPrev->pNext==pHdr ); | |
| 286 pHdr->pPrev->pNext = pHdr->pNext; | |
| 287 }else{ | |
| 288 assert( mem.pFirst==pHdr ); | |
| 289 mem.pFirst = pHdr->pNext; | |
| 290 } | |
| 291 if( pHdr->pNext ){ | |
| 292 assert( pHdr->pNext->pPrev==pHdr ); | |
| 293 pHdr->pNext->pPrev = pHdr->pPrev; | |
| 294 }else{ | |
| 295 assert( mem.pLast==pHdr ); | |
| 296 mem.pLast = pHdr->pPrev; | |
| 297 } | |
| 298 z = (char*)pBt; | |
| 299 z -= pHdr->nTitle; | |
| 300 adjustStats(pHdr->iSize, -1); | |
| 301 memset(z, 0x2b, sizeof(void*)*pHdr->nBacktraceSlots + sizeof(*pHdr) + | |
| 302 pHdr->iSize + sizeof(int) + pHdr->nTitle); | |
| 303 free(z); | |
| 304 sqlite3_mutex_leave(mem.mutex); | |
| 305 } | |
| 306 | |
| 307 /* | |
| 308 ** Change the size of an existing memory allocation. | |
| 309 ** | |
| 310 ** For this debugging implementation, we *always* make a copy of the | |
| 311 ** allocation into a new place in memory. In this way, if the | |
| 312 ** higher level code is using pointer to the old allocation, it is | |
| 313 ** much more likely to break and we are much more liking to find | |
| 314 ** the error. | |
| 315 */ | |
| 316 static void *sqlite3MemRealloc(void *pPrior, int nByte){ | |
| 317 struct MemBlockHdr *pOldHdr; | |
| 318 void *pNew; | |
| 319 assert( mem.disallow==0 ); | |
| 320 pOldHdr = sqlite3MemsysGetHeader(pPrior); | |
| 321 pNew = sqlite3MemMalloc(nByte); | |
| 322 if( pNew ){ | |
| 323 memcpy(pNew, pPrior, nByte<pOldHdr->iSize ? nByte : pOldHdr->iSize); | |
| 324 if( nByte>pOldHdr->iSize ){ | |
| 325 memset(&((char*)pNew)[pOldHdr->iSize], 0x2b, nByte - pOldHdr->iSize); | |
| 326 } | |
| 327 sqlite3MemFree(pPrior); | |
| 328 } | |
| 329 return pNew; | |
| 330 } | |
| 331 | |
| 332 /* | |
| 333 ** Populate the low-level memory allocation function pointers in | |
| 334 ** sqlite3GlobalConfig.m with pointers to the routines in this file. | |
| 335 */ | |
| 336 void sqlite3MemSetDefault(void){ | |
| 337 static const sqlite3_mem_methods defaultMethods = { | |
| 338 sqlite3MemMalloc, | |
| 339 sqlite3MemFree, | |
| 340 sqlite3MemRealloc, | |
| 341 sqlite3MemSize, | |
| 342 sqlite3MemRoundup, | |
| 343 sqlite3MemInit, | |
| 344 sqlite3MemShutdown, | |
| 345 0 | |
| 346 }; | |
| 347 sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods); | |
| 348 } | |
| 349 | |
| 350 /* | |
| 351 ** Set the number of backtrace levels kept for each allocation. | |
| 352 ** A value of zero turns off backtracing. The number is always rounded | |
| 353 ** up to a multiple of 2. | |
| 354 */ | |
| 355 void sqlite3MemdebugBacktrace(int depth){ | |
| 356 if( depth<0 ){ depth = 0; } | |
| 357 if( depth>20 ){ depth = 20; } | |
| 358 depth = (depth+1)&0xfe; | |
| 359 mem.nBacktrace = depth; | |
| 360 } | |
| 361 | |
| 362 void sqlite3MemdebugBacktraceCallback(void (*xBacktrace)(int, int, void **)){ | |
| 363 mem.xBacktrace = xBacktrace; | |
| 364 } | |
| 365 | |
| 366 /* | |
| 367 ** Set the title string for subsequent allocations. | |
| 368 */ | |
| 369 void sqlite3MemdebugSettitle(const char *zTitle){ | |
| 370 unsigned int n = sqlite3Strlen30(zTitle) + 1; | |
| 371 sqlite3_mutex_enter(mem.mutex); | |
| 372 if( n>=sizeof(mem.zTitle) ) n = sizeof(mem.zTitle)-1; | |
| 373 memcpy(mem.zTitle, zTitle, n); | |
| 374 mem.zTitle[n] = 0; | |
| 375 mem.nTitle = ROUND8(n); | |
| 376 sqlite3_mutex_leave(mem.mutex); | |
| 377 } | |
| 378 | |
| 379 void sqlite3MemdebugSync(){ | |
| 380 struct MemBlockHdr *pHdr; | |
| 381 for(pHdr=mem.pFirst; pHdr; pHdr=pHdr->pNext){ | |
| 382 void **pBt = (void**)pHdr; | |
| 383 pBt -= pHdr->nBacktraceSlots; | |
| 384 mem.xBacktrace(pHdr->iSize, pHdr->nBacktrace-1, &pBt[1]); | |
| 385 } | |
| 386 } | |
| 387 | |
| 388 /* | |
| 389 ** Open the file indicated and write a log of all unfreed memory | |
| 390 ** allocations into that log. | |
| 391 */ | |
| 392 void sqlite3MemdebugDump(const char *zFilename){ | |
| 393 FILE *out; | |
| 394 struct MemBlockHdr *pHdr; | |
| 395 void **pBt; | |
| 396 int i; | |
| 397 out = fopen(zFilename, "w"); | |
| 398 if( out==0 ){ | |
| 399 fprintf(stderr, "** Unable to output memory debug output log: %s **\n", | |
| 400 zFilename); | |
| 401 return; | |
| 402 } | |
| 403 for(pHdr=mem.pFirst; pHdr; pHdr=pHdr->pNext){ | |
| 404 char *z = (char*)pHdr; | |
| 405 z -= pHdr->nBacktraceSlots*sizeof(void*) + pHdr->nTitle; | |
| 406 fprintf(out, "**** %lld bytes at %p from %s ****\n", | |
| 407 pHdr->iSize, &pHdr[1], pHdr->nTitle ? z : "???"); | |
| 408 if( pHdr->nBacktrace ){ | |
| 409 fflush(out); | |
| 410 pBt = (void**)pHdr; | |
| 411 pBt -= pHdr->nBacktraceSlots; | |
| 412 backtrace_symbols_fd(pBt, pHdr->nBacktrace, fileno(out)); | |
| 413 fprintf(out, "\n"); | |
| 414 } | |
| 415 } | |
| 416 fprintf(out, "COUNTS:\n"); | |
| 417 for(i=0; i<NCSIZE-1; i++){ | |
| 418 if( mem.nAlloc[i] ){ | |
| 419 fprintf(out, " %5d: %10d %10d %10d\n", | |
| 420 i*8, mem.nAlloc[i], mem.nCurrent[i], mem.mxCurrent[i]); | |
| 421 } | |
| 422 } | |
| 423 if( mem.nAlloc[NCSIZE-1] ){ | |
| 424 fprintf(out, " %5d: %10d %10d %10d\n", | |
| 425 NCSIZE*8-8, mem.nAlloc[NCSIZE-1], | |
| 426 mem.nCurrent[NCSIZE-1], mem.mxCurrent[NCSIZE-1]); | |
| 427 } | |
| 428 fclose(out); | |
| 429 } | |
| 430 | |
| 431 /* | |
| 432 ** Return the number of times sqlite3MemMalloc() has been called. | |
| 433 */ | |
| 434 int sqlite3MemdebugMallocCount(){ | |
| 435 int i; | |
| 436 int nTotal = 0; | |
| 437 for(i=0; i<NCSIZE; i++){ | |
| 438 nTotal += mem.nAlloc[i]; | |
| 439 } | |
| 440 return nTotal; | |
| 441 } | |
| 442 | |
| 443 | |
| 444 #endif /* SQLITE_MEMDEBUG */ | |
| OLD | NEW |