diff options
author | drh <drh@noemail.net> | 2014-09-18 21:25:33 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2014-09-18 21:25:33 +0000 |
commit | 17bcb102993a155dec69a58e2f079a880e1967b7 (patch) | |
tree | 8abc9f4462b8269582e7e4aa23c7af3dd82dd360 /src | |
parent | 26c79a060b2e7fdf6d05585a3b44d0498df3fe1c (diff) | |
download | sqlite-17bcb102993a155dec69a58e2f079a880e1967b7.tar.gz sqlite-17bcb102993a155dec69a58e2f079a880e1967b7.zip |
Add the Mem.szMalloc element to the Mem object and use it to keep track of
the size of the Mem.zMalloc allocation.
FossilOrigin-Name: 9c09ac353df6041808cace41880f4729ee73f5e1
Diffstat (limited to 'src')
-rw-r--r-- | src/malloc.c | 19 | ||||
-rw-r--r-- | src/test_func.c | 4 | ||||
-rw-r--r-- | src/utf.c | 1 | ||||
-rw-r--r-- | src/vdbe.c | 11 | ||||
-rw-r--r-- | src/vdbeInt.h | 4 | ||||
-rw-r--r-- | src/vdbeapi.c | 2 | ||||
-rw-r--r-- | src/vdbeaux.c | 29 | ||||
-rw-r--r-- | src/vdbemem.c | 41 |
8 files changed, 62 insertions, 49 deletions
diff --git a/src/malloc.c b/src/malloc.c index e0d5b5ff9..8ba5fa0a8 100644 --- a/src/malloc.c +++ b/src/malloc.c @@ -451,15 +451,18 @@ int sqlite3MallocSize(void *p){ return sqlite3GlobalConfig.m.xSize(p); } int sqlite3DbMallocSize(sqlite3 *db, void *p){ - assert( db!=0 ); - assert( sqlite3_mutex_held(db->mutex) ); - if( isLookaside(db, p) ){ - return db->lookaside.sz; + if( db==0 ){ + return sqlite3MallocSize(p); }else{ - assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) ); - assert( sqlite3MemdebugHasType(p, MEMTYPE_LOOKASIDE|MEMTYPE_HEAP) ); - assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) ); - return sqlite3GlobalConfig.m.xSize(p); + assert( sqlite3_mutex_held(db->mutex) ); + if( isLookaside(db, p) ){ + return db->lookaside.sz; + }else{ + assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) ); + assert( sqlite3MemdebugHasType(p, MEMTYPE_LOOKASIDE|MEMTYPE_HEAP) ); + assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) ); + return sqlite3GlobalConfig.m.xSize(p); + } } } sqlite3_uint64 sqlite3_msize(void *p){ diff --git a/src/test_func.c b/src/test_func.c index 9cf2f8002..c7850631d 100644 --- a/src/test_func.c +++ b/src/test_func.c @@ -504,7 +504,7 @@ static void test_extract( sqlite3_result_value(context, &mem); } - sqlite3DbFree(db, mem.zMalloc); + if( mem.szMalloc ) sqlite3DbFree(db, mem.zMalloc); } } @@ -591,7 +591,7 @@ static void test_decode( Tcl_ListObjAppendElement(0, pRet, pVal); - if( mem.zMalloc ){ + if( mem.szMalloc ){ sqlite3DbFree(db, mem.zMalloc); } } @@ -320,6 +320,7 @@ SQLITE_NOINLINE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){ pMem->enc = desiredEnc; pMem->z = (char*)zOut; pMem->zMalloc = pMem->z; + pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->z); translate_out: #if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG) diff --git a/src/vdbe.c b/src/vdbe.c index 996cf8b9b..4a63f30af 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -1026,9 +1026,9 @@ case OP_String8: { /* same as TK_STRING, out2-prerelease */ rc = sqlite3VdbeMemSetStr(pOut, pOp->p4.z, -1, SQLITE_UTF8, SQLITE_STATIC); if( rc==SQLITE_TOOBIG ) goto too_big; if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pOut, encoding) ) goto no_mem; - assert( pOut->zMalloc==pOut->z ); + assert( pOut->szMalloc>0 && pOut->zMalloc==pOut->z ); assert( VdbeMemDynamic(pOut)==0 ); - pOut->zMalloc = 0; + pOut->szMalloc = 0; pOut->flags |= MEM_Static; if( pOp->p4type==P4_DYNAMIC ){ sqlite3DbFree(db, pOp->p4.z); @@ -1148,7 +1148,6 @@ case OP_Variable: { /* out2-prerelease */ ** for P3 to be less than 1. */ case OP_Move: { - char *zMalloc; /* Holding variable for allocated memory */ int n; /* Number of registers left to copy */ int p1; /* Register to copy from */ int p2; /* Register to copy to */ @@ -1166,16 +1165,12 @@ case OP_Move: { assert( pIn1<=&aMem[(p->nMem-p->nCursor)] ); assert( memIsValid(pIn1) ); memAboutToChange(p, pOut); - sqlite3VdbeMemRelease(pOut); - zMalloc = pOut->zMalloc; - memcpy(pOut, pIn1, sizeof(Mem)); + sqlite3VdbeMemMove(pOut, pIn1); #ifdef SQLITE_DEBUG if( pOut->pScopyFrom>=&aMem[p1] && pOut->pScopyFrom<&aMem[p1+pOp->p3] ){ pOut->pScopyFrom += p1 - pOp->p2; } #endif - pIn1->flags = MEM_Undefined; - pIn1->zMalloc = zMalloc; REGISTER_TRACE(p2++, pOut); pIn1++; pOut++; diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 8e4405437..138e61d2c 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -174,7 +174,9 @@ struct Mem { int n; /* Number of characters in string value, excluding '\0' */ char *z; /* String or BLOB value */ /* ShallowCopy only needs to copy the information above */ - char *zMalloc; /* Dynamic buffer allocated by sqlite3_malloc() */ + char *zMalloc; /* Space to hold MEM_Str or MEM_Blob if szMalloc>0 */ + int szMalloc; /* Size of the zMalloc allocation */ + int iPadding1; /* Padding for 8-byte alignment */ sqlite3 *db; /* The associated database connection */ void (*xDel)(void*);/* Destructor for Mem.z - only valid if MEM_Dyn */ #ifdef SQLITE_DEBUG diff --git a/src/vdbeapi.c b/src/vdbeapi.c index aad64aa64..7d3ae9cb0 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -809,6 +809,8 @@ static const Mem *columnNullValue(void){ /* .n = */ 0, /* .z = */ 0, /* .zMalloc = */ 0, + /* .szMalloc = */ 0, + /* .iPadding1 = */ 0, /* .db = */ 0, /* .xDel = */ 0, #ifdef SQLITE_DEBUG diff --git a/src/vdbeaux.c b/src/vdbeaux.c index ad57f4ccd..f990c40d4 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -698,7 +698,7 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){ sqlite3ValueFree((sqlite3_value*)p4); }else{ Mem *p = (Mem*)p4; - sqlite3DbFree(db, p->zMalloc); + if( p->szMalloc ) sqlite3DbFree(db, p->zMalloc); sqlite3DbFree(db, p); } break; @@ -1231,7 +1231,7 @@ static void releaseMemArray(Mem *p, int N){ u8 malloc_failed = db->mallocFailed; if( db->pnBytesFreed ){ for(pEnd=&p[N]; p<pEnd; p++){ - sqlite3DbFree(db, p->zMalloc); + if( p->szMalloc ) sqlite3DbFree(db, p->zMalloc); } return; } @@ -1257,9 +1257,9 @@ static void releaseMemArray(Mem *p, int N){ testcase( p->flags & MEM_RowSet ); if( p->flags&(MEM_Agg|MEM_Dyn|MEM_Frame|MEM_RowSet) ){ sqlite3VdbeMemRelease(p); - }else if( p->zMalloc ){ + }else if( p->szMalloc ){ sqlite3DbFree(db, p->zMalloc); - p->zMalloc = 0; + p->szMalloc = 0; } p->flags = MEM_Undefined; @@ -3167,7 +3167,7 @@ void sqlite3VdbeRecordUnpack( pMem->enc = pKeyInfo->enc; pMem->db = pKeyInfo->db; /* pMem->flags = 0; // sqlite3VdbeSerialGet() will set this for us */ - pMem->zMalloc = 0; + pMem->szMalloc = 0; d += sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem); pMem++; if( (++u)>=p->nField ) break; @@ -3207,7 +3207,7 @@ static int vdbeRecordCompareDebug( mem1.enc = pKeyInfo->enc; mem1.db = pKeyInfo->db; /* mem1.flags = 0; // Will be initialized by sqlite3VdbeSerialGet() */ - VVA_ONLY( mem1.zMalloc = 0; ) /* Only needed by assert() statements */ + VVA_ONLY( mem1.szMalloc = 0; ) /* Only needed by assert() statements */ /* Compilers may complain that mem1.u.i is potentially uninitialized. ** We could initialize it, as shown here, to silence those complaints. @@ -3250,7 +3250,7 @@ static int vdbeRecordCompareDebug( */ rc = sqlite3MemCompare(&mem1, &pPKey2->aMem[i], pKeyInfo->aColl[i]); if( rc!=0 ){ - assert( mem1.zMalloc==0 ); /* See comment below */ + assert( mem1.szMalloc==0 ); /* See comment below */ if( pKeyInfo->aSortOrder[i] ){ rc = -rc; /* Invert the result for DESC sort order. */ } @@ -3263,7 +3263,7 @@ static int vdbeRecordCompareDebug( ** the following assert(). If the assert() fails, it indicates a ** memory leak and a need to call sqlite3VdbeMemRelease(&mem1). */ - assert( mem1.zMalloc==0 ); + assert( mem1.szMalloc==0 ); /* rc==0 here means that one of the keys ran out of fields and ** all the fields up to that point were equal. Return the default_rc @@ -3302,9 +3302,8 @@ static int vdbeCompareMemString( int n1, n2; Mem c1; Mem c2; - c1.db = c2.db = pMem1->db; - c1.flags = c2.flags = 0; - c1.zMalloc = c2.zMalloc = 0; + sqlite3VdbeMemInit(&c1, pMem1->db, MEM_Null); + sqlite3VdbeMemInit(&c2, pMem1->db, MEM_Null); sqlite3VdbeMemShallowCopy(&c1, pMem1, MEM_Ephem); sqlite3VdbeMemShallowCopy(&c2, pMem2, MEM_Ephem); v1 = sqlite3ValueText((sqlite3_value*)&c1, pColl->enc); @@ -3516,7 +3515,7 @@ static int vdbeRecordCompareWithSkip( i = 0; } - VVA_ONLY( mem1.zMalloc = 0; ) /* Only needed by assert() statements */ + VVA_ONLY( mem1.szMalloc = 0; ) /* Only needed by assert() statements */ assert( pPKey2->pKeyInfo->nField+pPKey2->pKeyInfo->nXField>=pPKey2->nField || CORRUPT_DB ); assert( pPKey2->pKeyInfo->aSortOrder!=0 ); @@ -3639,7 +3638,7 @@ static int vdbeRecordCompareWithSkip( rc = -rc; } assert( vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, rc) ); - assert( mem1.zMalloc==0 ); /* See comment below */ + assert( mem1.szMalloc==0 ); /* See comment below */ return rc; } @@ -3652,7 +3651,7 @@ static int vdbeRecordCompareWithSkip( /* No memory allocation is ever used on mem1. Prove this using ** the following assert(). If the assert() fails, it indicates a ** memory leak and a need to call sqlite3VdbeMemRelease(&mem1). */ - assert( mem1.zMalloc==0 ); + assert( mem1.szMalloc==0 ); /* rc==0 here means that one or both of the keys ran out of fields and ** all the fields up to that point were equal. Return the default_rc @@ -3937,7 +3936,7 @@ int sqlite3VdbeIdxRowid(sqlite3 *db, BtCursor *pCur, i64 *rowid){ /* Jump here if database corruption is detected after m has been ** allocated. Free the m object and return SQLITE_CORRUPT. */ idx_rowid_corruption: - testcase( m.zMalloc!=0 ); + testcase( m.szMalloc!=0 ); sqlite3VdbeMemRelease(&m); return SQLITE_CORRUPT_BKPT; } diff --git a/src/vdbemem.c b/src/vdbemem.c index 780bc5286..4ea28f841 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -34,6 +34,10 @@ int sqlite3VdbeCheckMemInvariants(Mem *p){ /* Cannot be both MEM_Int and MEM_Real at the same time */ assert( (p->flags & (MEM_Int|MEM_Real))!=(MEM_Int|MEM_Real) ); + /* The szMalloc field holds the correct memory allocation size */ + assert( p->szMalloc==0 + || p->szMalloc==sqlite3DbMallocSize(p->db,p->zMalloc) ); + /* If p holds a string or blob, the Mem.z must point to exactly ** one of the following: ** @@ -42,9 +46,9 @@ int sqlite3VdbeCheckMemInvariants(Mem *p){ ** (3) An ephemeral string or blob ** (4) A static string or blob */ - if( (p->flags & (MEM_Str|MEM_Blob)) && p->z!=0 ){ + if( (p->flags & (MEM_Str|MEM_Blob)) && p->n>0 ){ assert( - ((p->z==p->zMalloc)? 1 : 0) + + ((p->szMalloc>0 && p->z==p->zMalloc)? 1 : 0) + ((p->flags&MEM_Dyn)!=0 ? 1 : 0) + ((p->flags&MEM_Ephem)!=0 ? 1 : 0) + ((p->flags&MEM_Static)!=0 ? 1 : 0) == 1 @@ -112,19 +116,24 @@ int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){ assert( bPreserve==0 || pMem->flags&(MEM_Blob|MEM_Str) ); testcase( bPreserve && pMem->z==0 ); - if( pMem->zMalloc==0 || sqlite3DbMallocSize(pMem->db, pMem->zMalloc)<n ){ + assert( pMem->szMalloc==0 + || pMem->szMalloc==sqlite3DbMallocSize(pMem->db, pMem->zMalloc) ); + if( pMem->szMalloc<n ){ if( n<32 ) n = 32; - if( bPreserve && pMem->z==pMem->zMalloc ){ + if( bPreserve && pMem->szMalloc>0 && pMem->z==pMem->zMalloc ){ pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n); bPreserve = 0; }else{ - sqlite3DbFree(pMem->db, pMem->zMalloc); + if( pMem->szMalloc>0 ) sqlite3DbFree(pMem->db, pMem->zMalloc); pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, n); } if( pMem->zMalloc==0 ){ sqlite3VdbeMemSetNull(pMem); pMem->z = 0; + pMem->szMalloc = 0; return SQLITE_NOMEM; + }else{ + pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc); } } @@ -155,7 +164,7 @@ int sqlite3VdbeMemMakeWriteable(Mem *pMem){ assert( (pMem->flags&MEM_RowSet)==0 ); ExpandBlob(pMem); f = pMem->flags; - if( (f&(MEM_Str|MEM_Blob)) && pMem->z!=pMem->zMalloc ){ + if( (f&(MEM_Str|MEM_Blob)) && (pMem->szMalloc==0 || pMem->z!=pMem->zMalloc) ){ if( sqlite3VdbeMemGrow(pMem, pMem->n + 2, 1) ){ return SQLITE_NOMEM; } @@ -301,7 +310,7 @@ int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){ ctx.pFunc = pFunc; pFunc->xFinalize(&ctx); /* IMP: R-24505-23230 */ assert( (pMem->flags & MEM_Dyn)==0 ); - sqlite3DbFree(pMem->db, pMem->zMalloc); + if( pMem->szMalloc>0 ) sqlite3DbFree(pMem->db, pMem->zMalloc); memcpy(pMem, &t, sizeof(t)); rc = ctx.isError; } @@ -351,9 +360,9 @@ static SQLITE_NOINLINE void vdbeMemClear(Mem *p){ if( VdbeMemDynamic(p) ){ vdbeMemClearExternAndSetNull(p); } - if( p->zMalloc ){ + if( p->szMalloc ){ sqlite3DbFree(p->db, p->zMalloc); - p->zMalloc = 0; + p->szMalloc = 0; } p->z = 0; } @@ -370,7 +379,7 @@ static SQLITE_NOINLINE void vdbeMemClear(Mem *p){ */ void sqlite3VdbeMemRelease(Mem *p){ assert( sqlite3VdbeCheckMemInvariants(p) ); - if( VdbeMemDynamic(p) || p->zMalloc ){ + if( VdbeMemDynamic(p) || p->szMalloc ){ vdbeMemClear(p); } } @@ -592,7 +601,7 @@ void sqlite3VdbeMemInit(Mem *pMem, sqlite3 *db, u16 flags){ assert( (flags & ~MEM_TypeMask)==0 ); pMem->flags = flags; pMem->db = db; - pMem->zMalloc = 0; + pMem->szMalloc = 0; } @@ -683,10 +692,11 @@ void sqlite3VdbeMemSetRowSet(Mem *pMem){ pMem->zMalloc = sqlite3DbMallocRaw(db, 64); if( db->mallocFailed ){ pMem->flags = MEM_Null; + pMem->szMalloc = 0; }else{ assert( pMem->zMalloc ); - pMem->u.pRowSet = sqlite3RowSetInit(db, pMem->zMalloc, - sqlite3DbMallocSize(db, pMem->zMalloc)); + pMem->szMalloc = sqlite3DbMallocSize(db, pMem->zMalloc); + pMem->u.pRowSet = sqlite3RowSetInit(db, pMem->zMalloc, pMem->szMalloc); assert( pMem->u.pRowSet!=0 ); pMem->flags = MEM_RowSet; } @@ -789,7 +799,7 @@ void sqlite3VdbeMemMove(Mem *pTo, Mem *pFrom){ sqlite3VdbeMemRelease(pTo); memcpy(pTo, pFrom, sizeof(Mem)); pFrom->flags = MEM_Null; - pFrom->zMalloc = 0; + pFrom->szMalloc = 0; } /* @@ -863,6 +873,7 @@ int sqlite3VdbeMemSetStr( }else if( xDel==SQLITE_DYNAMIC ){ sqlite3VdbeMemRelease(pMem); pMem->zMalloc = pMem->z = (char *)z; + pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc); }else{ sqlite3VdbeMemRelease(pMem); pMem->z = (char *)z; @@ -1485,7 +1496,7 @@ void sqlite3Stat4ProbeFree(UnpackedRecord *pRec){ Mem *aMem = pRec->aMem; sqlite3 *db = aMem[0].db; for(i=0; i<nCol; i++){ - sqlite3DbFree(db, aMem[i].zMalloc); + if( aMem[i].szMalloc ) sqlite3DbFree(db, aMem[i].zMalloc); } sqlite3KeyInfoUnref(pRec->pKeyInfo); sqlite3DbFree(db, pRec); |