📄 malloc.c
字号:
z = &zAlloc[TESTALLOC_OFFSET_LINENUMBER(p)]; memcpy(&iLine, z, sizeof(u32)); Tcl_ListObjAppendElement(0, pEntry, Tcl_NewIntObj(iLine)); z = &zAlloc[TESTALLOC_OFFSET_USER(p)]; Tcl_ListObjAppendElement(0, pEntry, Tcl_NewStringObj(z, -1)); z = &zAlloc[TESTALLOC_OFFSET_STACK(p)]; for(i=0; i<TESTALLOC_STACKFRAMES; i++){ char zHex[128]; sqlite3_snprintf(sizeof(zHex), zHex, "%p", ((void **)z)[i]); Tcl_ListObjAppendElement(0, pStack, Tcl_NewStringObj(zHex, -1)); } Tcl_ListObjAppendElement(0, pEntry, pStack); Tcl_ListObjAppendElement(0, pRes, pEntry); } Tcl_ResetResult(interp); Tcl_SetObjResult(interp, pRes); Tcl_DecrRefCount(pRes); return TCL_OK;}#endif/*** This is the test layer's wrapper around sqlite3OsMalloc().*/static void * OSMALLOC(int n){ sqlite3OsEnterMutex();#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT sqlite3_nMaxAlloc = MAX(sqlite3_nMaxAlloc, sqlite3ThreadDataReadOnly()->nAlloc);#endif assert( !sqlite3_mallocDisallowed ); if( !sqlite3TestMallocFail() ){ u32 *p; p = (u32 *)sqlite3OsMalloc(n + TESTALLOC_OVERHEAD); assert(p); sqlite3_nMalloc++; applyGuards(p); linkAlloc(p); sqlite3OsLeaveMutex(); return (void *)(&p[TESTALLOC_NGUARD + 2*sizeof(void *)/sizeof(u32)]); } sqlite3OsLeaveMutex(); return 0;}static int OSSIZEOF(void *p){ if( p ){ u32 *pOs = (u32 *)getOsPointer(p); return sqlite3OsAllocationSize(pOs) - TESTALLOC_OVERHEAD; } return 0;}/*** This is the test layer's wrapper around sqlite3OsFree(). The argument is a** pointer to the space allocated for the application to use.*/static void OSFREE(void *pFree){ u32 *p; /* Pointer to the OS-layer allocation */ sqlite3OsEnterMutex(); p = (u32 *)getOsPointer(pFree); checkGuards(p); unlinkAlloc(p); memset(pFree, 0x55, OSSIZEOF(pFree)); sqlite3OsFree(p); sqlite3_nFree++; sqlite3OsLeaveMutex();}/*** This is the test layer's wrapper around sqlite3OsRealloc().*/static void * OSREALLOC(void *pRealloc, int n){#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT sqlite3_nMaxAlloc = MAX(sqlite3_nMaxAlloc, sqlite3ThreadDataReadOnly()->nAlloc);#endif assert( !sqlite3_mallocDisallowed ); if( !sqlite3TestMallocFail() ){ u32 *p = (u32 *)getOsPointer(pRealloc); checkGuards(p); p = sqlite3OsRealloc(p, n + TESTALLOC_OVERHEAD); applyGuards(p); relinkAlloc(p); return (void *)(&p[TESTALLOC_NGUARD + 2*sizeof(void *)/sizeof(u32)]); } return 0;}static void OSMALLOC_FAILED(){ sqlite3_isFail = 0;}#else/* Define macros to call the sqlite3OsXXX interface directly if ** the SQLITE_MEMDEBUG macro is not defined.*/#define OSMALLOC(x) sqlite3OsMalloc(x)#define OSREALLOC(x,y) sqlite3OsRealloc(x,y)#define OSFREE(x) sqlite3OsFree(x)#define OSSIZEOF(x) sqlite3OsAllocationSize(x)#define OSMALLOC_FAILED()#endif /* SQLITE_MEMDEBUG *//*** End code for memory allocation system test layer.**--------------------------------------------------------------------------*//*** This routine is called when we are about to allocate n additional bytes** of memory. If the new allocation will put is over the soft allocation** limit, then invoke sqlite3_release_memory() to try to release some** memory before continuing with the allocation.**** This routine also makes sure that the thread-specific-data (TSD) has** be allocated. If it has not and can not be allocated, then return** false. The updateMemoryUsedCount() routine below will deallocate** the TSD if it ought to be.**** If SQLITE_ENABLE_MEMORY_MANAGEMENT is not defined, this routine is** a no-op*/ #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENTstatic int enforceSoftLimit(int n){ ThreadData *pTsd = sqlite3ThreadData(); if( pTsd==0 ){ return 0; } assert( pTsd->nAlloc>=0 ); if( n>0 && pTsd->nSoftHeapLimit>0 ){ while( pTsd->nAlloc+n>pTsd->nSoftHeapLimit && sqlite3_release_memory(n) ){} } return 1;}#else# define enforceSoftLimit(X) 1#endif/*** Update the count of total outstanding memory that is held in** thread-specific-data (TSD). If after this update the TSD is** no longer being used, then deallocate it.**** If SQLITE_ENABLE_MEMORY_MANAGEMENT is not defined, this routine is** a no-op*/#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENTstatic void updateMemoryUsedCount(int n){ ThreadData *pTsd = sqlite3ThreadData(); if( pTsd ){ pTsd->nAlloc += n; assert( pTsd->nAlloc>=0 ); if( pTsd->nAlloc==0 && pTsd->nSoftHeapLimit==0 ){ sqlite3ReleaseThreadData(); } }}#else#define updateMemoryUsedCount(x) /* no-op */#endif/*** Allocate and return N bytes of uninitialised memory by calling** sqlite3OsMalloc(). If the Malloc() call fails, attempt to free memory ** by calling sqlite3_release_memory().*/void *sqlite3MallocRaw(int n, int doMemManage){ void *p = 0; if( n>0 && !sqlite3MallocFailed() && (!doMemManage || enforceSoftLimit(n)) ){ while( (p = OSMALLOC(n))==0 && sqlite3_release_memory(n) ){} if( !p ){ sqlite3FailedMalloc(); OSMALLOC_FAILED(); }else if( doMemManage ){ updateMemoryUsedCount(OSSIZEOF(p)); } } return p;}/*** Resize the allocation at p to n bytes by calling sqlite3OsRealloc(). The** pointer to the new allocation is returned. If the Realloc() call fails,** attempt to free memory by calling sqlite3_release_memory().*/void *sqlite3Realloc(void *p, int n){ if( sqlite3MallocFailed() ){ return 0; } if( !p ){ return sqlite3Malloc(n, 1); }else{ void *np = 0;#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT int origSize = OSSIZEOF(p);#endif if( enforceSoftLimit(n - origSize) ){ while( (np = OSREALLOC(p, n))==0 && sqlite3_release_memory(n) ){} if( !np ){ sqlite3FailedMalloc(); OSMALLOC_FAILED(); }else{ updateMemoryUsedCount(OSSIZEOF(np) - origSize); } } return np; }}/*** Free the memory pointed to by p. p must be either a NULL pointer or a ** value returned by a previous call to sqlite3Malloc() or sqlite3Realloc().*/void sqlite3FreeX(void *p){ if( p ){ updateMemoryUsedCount(0 - OSSIZEOF(p)); OSFREE(p); }}/*** A version of sqliteMalloc() that is always a function, not a macro.** Currently, this is used only to alloc to allocate the parser engine.*/void *sqlite3MallocX(int n){ return sqliteMalloc(n);}/*** sqlite3Malloc** sqlite3ReallocOrFree**** These two are implemented as wrappers around sqlite3MallocRaw(), ** sqlite3Realloc() and sqlite3Free().*/ void *sqlite3Malloc(int n, int doMemManage){ void *p = sqlite3MallocRaw(n, doMemManage); if( p ){ memset(p, 0, n); } return p;}void *sqlite3ReallocOrFree(void *p, int n){ void *pNew; pNew = sqlite3Realloc(p, n); if( !pNew ){ sqlite3FreeX(p); } return pNew;}/*** sqlite3ThreadSafeMalloc() and sqlite3ThreadSafeFree() are used in those** rare scenarios where sqlite may allocate memory in one thread and free** it in another. They are exactly the same as sqlite3Malloc() and ** sqlite3Free() except that:**** * The allocated memory is not included in any calculations with ** respect to the soft-heap-limit, and**** * sqlite3ThreadSafeMalloc() must be matched with ThreadSafeFree(),** not sqlite3Free(). Calling sqlite3Free() on memory obtained from** ThreadSafeMalloc() will cause an error somewhere down the line.*/#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENTvoid *sqlite3ThreadSafeMalloc(int n){ (void)ENTER_MALLOC; return sqlite3Malloc(n, 0);}void sqlite3ThreadSafeFree(void *p){ (void)ENTER_MALLOC; if( p ){ OSFREE(p); }}#endif/*** Return the number of bytes allocated at location p. p must be either ** a NULL pointer (in which case 0 is returned) or a pointer returned by ** sqlite3Malloc(), sqlite3Realloc() or sqlite3ReallocOrFree().**** The number of bytes allocated does not include any overhead inserted by ** any malloc() wrapper functions that may be called. So the value returned** is the number of bytes that were available to SQLite using pointer p, ** regardless of how much memory was actually allocated.*/#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENTint sqlite3AllocSize(void *p){ return OSSIZEOF(p);}#endif/*** Make a copy of a string in memory obtained from sqliteMalloc(). These ** functions call sqlite3MallocRaw() directly instead of sqliteMalloc(). This** is because when memory debugging is turned on, these two functions are ** called via macros that record the current file and line number in the** ThreadData structure.*/char *sqlite3StrDup(const char *z){ char *zNew; int n; if( z==0 ) return 0; n = strlen(z)+1; zNew = sqlite3MallocRaw(n, 1); if( zNew ) memcpy(zNew, z, n); return zNew;}char *sqlite3StrNDup(const char *z, int n){ char *zNew; if( z==0 ) return 0; zNew = sqlite3MallocRaw(n+1, 1); if( zNew ){ memcpy(zNew, z, n); zNew[n] = 0; } return zNew;}/*** Create a string from the 2nd and subsequent arguments (up to the** first NULL argument), store the string in memory obtained from** sqliteMalloc() and make the pointer indicated by the 1st argument** point to that string. The 1st argument must either be NULL or ** point to memory obtained from sqliteMalloc().*/void sqlite3SetString(char **pz, ...){ va_list ap; int nByte; const char *z; char *zResult; assert( pz!=0 ); nByte = 1; va_start(ap, pz); while( (z = va_arg(ap, const char*))!=0 ){ nByte += strlen(z); } va_end(ap); sqliteFree(*pz); *pz = zResult = sqliteMallocRaw( nByte ); if( zResult==0 ){ return; } *zResult = 0; va_start(ap, pz); while( (z = va_arg(ap, const char*))!=0 ){ int n = strlen(z); memcpy(zResult, z, n); zResult += n; } zResult[0] = 0; va_end(ap);}/*** This function must be called before exiting any API function (i.e. ** returning control to the user) that has called sqlite3Malloc or** sqlite3Realloc.**** The returned value is normally a copy of the second argument to this** function. However, if a malloc() failure has occured since the previous** invocation SQLITE_NOMEM is returned instead. **** If the first argument, db, is not NULL and a malloc() error has occured,** then the connection error-code (the value returned by sqlite3_errcode())** is set to SQLITE_NOMEM.*/int sqlite3_mallocHasFailed = 0;int sqlite3ApiExit(sqlite3* db, int rc){ if( sqlite3MallocFailed() ){ sqlite3_mallocHasFailed = 0; sqlite3OsLeaveMutex(); sqlite3Error(db, SQLITE_NOMEM, 0); rc = SQLITE_NOMEM; } return rc & (db ? db->errMask : 0xff);}/* ** Set the "malloc has failed" condition to true for this thread.*/void sqlite3FailedMalloc(){ if( !sqlite3MallocFailed() ){ sqlite3OsEnterMutex(); assert( sqlite3_mallocHasFailed==0 ); sqlite3_mallocHasFailed = 1; }}#ifdef SQLITE_MEMDEBUG/*** This function sets a flag in the thread-specific-data structure that will** cause an assert to fail if sqliteMalloc() or sqliteRealloc() is called.*/void sqlite3MallocDisallow(){ assert( sqlite3_mallocDisallowed>=0 ); sqlite3_mallocDisallowed++;}/*** This function clears the flag set in the thread-specific-data structure set** by sqlite3MallocDisallow().*/void sqlite3MallocAllow(){ assert( sqlite3_mallocDisallowed>0 ); sqlite3_mallocDisallowed--;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -