📄 mem2.c
字号:
mem.sizeCnt[NCSIZE-1]++; }else{ mem.sizeCnt[nByte/8]++; } totalSize = nByte + sizeof(*pHdr) + sizeof(int) + mem.nBacktrace*sizeof(void*) + mem.nTitle; if( mem.iFail>0 ){ if( mem.iFail==1 ){ p = 0; mem.iFail = mem.iReset; if( mem.iFailCnt==0 ){ sqlite3MemsysFailed(); /* A place to set a breakpoint */ } mem.iFailCnt++; if( mem.iNextIsBenign || mem.iIsBenign ){ mem.iBenignFailCnt++; } }else{ p = malloc(totalSize); mem.iFail--; } }else{ p = malloc(totalSize); if( p==0 ){ sqlite3MemsysAlarm(nByte); p = malloc(totalSize); } } if( p ){ z = p; pBt = (void**)&z[mem.nTitle]; pHdr = (struct MemBlockHdr*)&pBt[mem.nBacktrace]; pHdr->pNext = 0; pHdr->pPrev = mem.pLast; if( mem.pLast ){ mem.pLast->pNext = pHdr; }else{ mem.pFirst = pHdr; } mem.pLast = pHdr; pHdr->iForeGuard = FOREGUARD; pHdr->nBacktraceSlots = mem.nBacktrace; pHdr->nTitle = mem.nTitle; if( mem.nBacktrace ){ void *aAddr[40]; pHdr->nBacktrace = backtrace(aAddr, mem.nBacktrace+1)-1; memcpy(pBt, &aAddr[1], pHdr->nBacktrace*sizeof(void*)); }else{ pHdr->nBacktrace = 0; } if( mem.nTitle ){ memcpy(z, mem.zTitle, mem.nTitle); } pHdr->iSize = nByte; pInt = (int*)&pHdr[1]; pInt[nByte/sizeof(int)] = REARGUARD; memset(pInt, 0x65, nByte); mem.nowUsed += nByte; if( mem.nowUsed>mem.mxUsed ){ mem.mxUsed = mem.nowUsed; } p = (void*)pInt; } sqlite3_mutex_leave(mem.mutex); } mem.iNextIsBenign = 0; return p; }/*** Free memory.*/void sqlite3_free(void *pPrior){ struct MemBlockHdr *pHdr; void **pBt; char *z; if( pPrior==0 ){ return; } assert( mem.mutex!=0 ); pHdr = sqlite3MemsysGetHeader(pPrior); pBt = (void**)pHdr; pBt -= pHdr->nBacktraceSlots; sqlite3_mutex_enter(mem.mutex); mem.nowUsed -= pHdr->iSize; if( pHdr->pPrev ){ assert( pHdr->pPrev->pNext==pHdr ); pHdr->pPrev->pNext = pHdr->pNext; }else{ assert( mem.pFirst==pHdr ); mem.pFirst = pHdr->pNext; } if( pHdr->pNext ){ assert( pHdr->pNext->pPrev==pHdr ); pHdr->pNext->pPrev = pHdr->pPrev; }else{ assert( mem.pLast==pHdr ); mem.pLast = pHdr->pPrev; } z = (char*)pBt; z -= pHdr->nTitle; memset(z, 0x2b, sizeof(void*)*pHdr->nBacktraceSlots + sizeof(*pHdr) + pHdr->iSize + sizeof(int) + pHdr->nTitle); free(z); sqlite3_mutex_leave(mem.mutex); }/*** Change the size of an existing memory allocation.**** For this debugging implementation, we *always* make a copy of the** allocation into a new place in memory. In this way, if the ** higher level code is using pointer to the old allocation, it is ** much more likely to break and we are much more liking to find** the error.*/void *sqlite3_realloc(void *pPrior, int nByte){ struct MemBlockHdr *pOldHdr; void *pNew; if( pPrior==0 ){ return sqlite3_malloc(nByte); } if( nByte<=0 ){ sqlite3_free(pPrior); return 0; } assert( mem.disallow==0 ); pOldHdr = sqlite3MemsysGetHeader(pPrior); pNew = sqlite3_malloc(nByte); if( pNew ){ memcpy(pNew, pPrior, nByte<pOldHdr->iSize ? nByte : pOldHdr->iSize); if( nByte>pOldHdr->iSize ){ memset(&((char*)pNew)[pOldHdr->iSize], 0x2b, nByte - pOldHdr->iSize); } sqlite3_free(pPrior); } return pNew;}/*** Set the number of backtrace levels kept for each allocation.** A value of zero turns of backtracing. The number is always rounded** up to a multiple of 2.*/void sqlite3_memdebug_backtrace(int depth){ if( depth<0 ){ depth = 0; } if( depth>20 ){ depth = 20; } depth = (depth+1)&0xfe; mem.nBacktrace = depth;}/*** Set the title string for subsequent allocations.*/void sqlite3_memdebug_settitle(const char *zTitle){ int n = strlen(zTitle) + 1; enterMem(); if( n>=sizeof(mem.zTitle) ) n = sizeof(mem.zTitle)-1; memcpy(mem.zTitle, zTitle, n); mem.zTitle[n] = 0; mem.nTitle = (n+3)&~3; sqlite3_mutex_leave(mem.mutex);}/*** Open the file indicated and write a log of all unfreed memory ** allocations into that log.*/void sqlite3_memdebug_dump(const char *zFilename){ FILE *out; struct MemBlockHdr *pHdr; void **pBt; int i; out = fopen(zFilename, "w"); if( out==0 ){ fprintf(stderr, "** Unable to output memory debug output log: %s **\n", zFilename); return; } for(pHdr=mem.pFirst; pHdr; pHdr=pHdr->pNext){ char *z = (char*)pHdr; z -= pHdr->nBacktraceSlots*sizeof(void*) + pHdr->nTitle; fprintf(out, "**** %d bytes at %p from %s ****\n", pHdr->iSize, &pHdr[1], pHdr->nTitle ? z : "???"); if( pHdr->nBacktrace ){ fflush(out); pBt = (void**)pHdr; pBt -= pHdr->nBacktraceSlots; backtrace_symbols_fd(pBt, pHdr->nBacktrace, fileno(out)); fprintf(out, "\n"); } } fprintf(out, "COUNTS:\n"); for(i=0; i<NCSIZE-1; i++){ if( mem.sizeCnt[i] ){ fprintf(out, " %3d: %d\n", i*8+8, mem.sizeCnt[i]); } } if( mem.sizeCnt[NCSIZE-1] ){ fprintf(out, " >%3d: %d\n", NCSIZE*8, mem.sizeCnt[NCSIZE-1]); } fclose(out);}/*** This routine is used to simulate malloc failures.**** After calling this routine, there will be iFail successful** memory allocations and then a failure. If iRepeat is 1** all subsequent memory allocations will fail. If iRepeat is** 0, only a single allocation will fail. If iRepeat is negative** then the previous setting for iRepeat is unchanged.**** Each call to this routine overrides the previous. To disable** the simulated allocation failure mechanism, set iFail to -1.**** This routine returns the number of simulated failures that have** occurred since the previous call.*/int sqlite3_memdebug_fail(int iFail, int iRepeat, int *piBenign){ int n = mem.iFailCnt; if( piBenign ){ *piBenign = mem.iBenignFailCnt; } mem.iFail = iFail+1; if( iRepeat>=0 ){ mem.iReset = iRepeat; } mem.iFailCnt = 0; mem.iBenignFailCnt = 0; return n;}int sqlite3_memdebug_pending(){ return (mem.iFail-1);}/*** The following three functions are used to indicate to the test ** infrastructure which malloc() calls may fail benignly without** affecting functionality. This can happen when resizing hash tables ** (failing to resize a hash-table is a performance hit, but not an ** error) or sometimes during a rollback operation.**** If the argument is true, sqlite3MallocBenignFailure() indicates that the** next call to allocate memory may fail benignly.**** If sqlite3MallocEnterBenignBlock() is called with a non-zero argument,** then all memory allocations requested before the next call to** sqlite3MallocLeaveBenignBlock() may fail benignly.*/void sqlite3MallocBenignFailure(int isBenign){ if( isBenign ){ mem.iNextIsBenign = 1; }}void sqlite3MallocEnterBenignBlock(int isBenign){ if( isBenign ){ mem.iIsBenign = 1; }}void sqlite3MallocLeaveBenignBlock(){ mem.iIsBenign = 0;}/*** The following two routines are used to assert that no memory** allocations occur between one call and the next. The use of** these routines does not change the computed results in any way.** These routines are like asserts.*/void sqlite3MallocDisallow(void){ assert( mem.mutex!=0 ); sqlite3_mutex_enter(mem.mutex); mem.disallow++; sqlite3_mutex_leave(mem.mutex);}void sqlite3MallocAllow(void){ assert( mem.mutex ); sqlite3_mutex_enter(mem.mutex); assert( mem.disallow>0 ); mem.disallow--; sqlite3_mutex_leave(mem.mutex);}#endif /* SQLITE_MEMDEBUG && !SQLITE_OMIT_MEMORY_ALLOCATION */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -