/ Check-in [81a41f66]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Move malloc(), free(), realloc() and allocationSize() into the Os vtbl. (CVS 2819)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:81a41f66370ea7f6810dfb323ba5cea60f240edd
User & Date: danielk1977 2005-12-15 10:50:54
Context
2005-12-15
15:22
Add the sqlite3_update_hook() API. (CVS 2820) check-in: 36229018 user: danielk1977 tags: trunk
10:50
Move malloc(), free(), realloc() and allocationSize() into the Os vtbl. (CVS 2819) check-in: 81a41f66 user: danielk1977 tags: trunk
10:11
Add the sqlite3_os_routine_set()/get() functions. (CVS 2818) check-in: c1ed79f5 user: danielk1977 tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/os.h.

216
217
218
219
220
221
222

223
224
225





226
227
228
229
230
231
232
  int (*xIsDirWritable)(char*);
  int (*xSyncDirectory)(const char*);
  int (*xTempFileName)(char*);

  int  (*xRandomSeed)(char*);
  int  (*xSleep)(int ms);
  int  (*xCurrentTime)(double*);

  void (*xEnterMutex)(void);
  void (*xLeaveMutex)(void);
  void *(*xThreadSpecificData)(int);





} sqlite3Os;


/*
** The semi-published API for setting and getting methods from the 
** global sqlite3OsVtbl structure. Neither sqlite3_os_routine_XXX() function
** is intriniscally thread-safe.







>



>
>
>
>
>







216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
  int (*xIsDirWritable)(char*);
  int (*xSyncDirectory)(const char*);
  int (*xTempFileName)(char*);

  int  (*xRandomSeed)(char*);
  int  (*xSleep)(int ms);
  int  (*xCurrentTime)(double*);

  void (*xEnterMutex)(void);
  void (*xLeaveMutex)(void);
  void *(*xThreadSpecificData)(int);

  void *(*xMalloc)(int);
  void *(*xRealloc)(void *, int);
  void (*xFree)(void *);
  int (*xAllocationSize)(void *);
} sqlite3Os;


/*
** The semi-published API for setting and getting methods from the 
** global sqlite3OsVtbl structure. Neither sqlite3_os_routine_XXX() function
** is intriniscally thread-safe.

Changes to src/os_common.h.

118
119
120
121
122
123
124





































*/
#ifdef SQLITE_TEST
int sqlite3_open_file_count = 0;
#define OpenCounter(X)  sqlite3_open_file_count+=(X)
#else
#define OpenCounter(X)
#endif












































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
*/
#ifdef SQLITE_TEST
int sqlite3_open_file_count = 0;
#define OpenCounter(X)  sqlite3_open_file_count+=(X)
#else
#define OpenCounter(X)
#endif

/*
** genericMalloc
** genericRealloc
** genericOsFree
** genericAllocationSize
**
** Implementation of the os level dynamic memory allocation interface in terms
** of the standard malloc(), realloc() and free() found in many operating
** systems. No rocket science here.
*/
static void *genericMalloc(int n){
  char *p = (char *)malloc(n+8);
  assert(n>0);
  assert(sizeof(int)<=8);
  if( p ){
    *(int *)p = n;
  }
  return (void *)(p + 8);
}
static void *genericRealloc(void *p, int n){
  char *p2 = ((char *)p - 8);
  assert(n>0);
  p2 = realloc(p2, n+8);
  if( p2 ){
    *(int *)p2 = n;
  }
  return (void *)((char *)p2 + 8);
}
static void genericFree(void *p){
  assert(p);
  free((void *)((char *)p - 8));
}
static int genericAllocationSize(void *p){
  return *(int *)((char *)p - 8);
}

Changes to src/os_unix.c.

1590
1591
1592
1593
1594
1595
1596

1597
1598
1599

1600
1601
1602
1603
1604
1605
1606
....
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
....
1700
1701
1702
1703
1704
1705
1706
1707




1708
1709
1710
1711
1712
** This function is called automatically when a thread exists to delete
** the threads SqliteTsd structure. 
**
** Because the SqliteTsd structure is required by higher level routines
** such as sqliteMalloc() we use OsFree() and OsMalloc() directly to
** allocate the thread specific data.
*/

static void deleteTsd(void *pTsd){
  sqlite3OsFree(pTsd);
}


/* 
** The first time this function is called from a specific thread, nByte 
** bytes of data area are allocated and zeroed. A pointer to the new 
** allocation is returned to the caller. 
**
** Each subsequent call to this function from the thread returns the same
................................................................................
      keyInit = 1;
    }
    sqlite3Os.xLeaveMutex();
  }

  pTsd = (SqliteTsd *)pthread_getspecific(key);
  if( !pTsd ){
    pTsd = sqlite3OsMalloc(sizeof(SqliteTsd));
    if( pTsd ){
      memset(pTsd, 0, sizeof(SqliteTsd));
      pthread_setspecific(key, pTsd);
    }
  }
  return pTsd;
#else
  static char tsd[sizeof(SqliteTsd)];
  static isInit = 0;
  assert( nByte==sizeof(SqliteTsd) );
  if( !isInit ){
    memset(tsd, 0, sizeof(SqliteTsd));
    isInit = 1;
  }
  return (void *)tsd;
#endif
................................................................................
  IF_DISKIO( unixSyncDirectory ),
  IF_DISKIO( unixTempFileName ),
  unixRandomSeed,
  unixSleep,
  unixCurrentTime,
  unixEnterMutex,
  unixLeaveMutex,
  unixThreadSpecificData




};



#endif /* OS_UNIX */







>

|

>







 







|








|







 







|
>
>
>
>





1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
....
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
....
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
** This function is called automatically when a thread exists to delete
** the threads SqliteTsd structure. 
**
** Because the SqliteTsd structure is required by higher level routines
** such as sqliteMalloc() we use OsFree() and OsMalloc() directly to
** allocate the thread specific data.
*/
#ifdef SQLITE_UNIX_THREADS
static void deleteTsd(void *pTsd){
  sqlite3Os.xFree(pTsd);
}
#endif

/* 
** The first time this function is called from a specific thread, nByte 
** bytes of data area are allocated and zeroed. A pointer to the new 
** allocation is returned to the caller. 
**
** Each subsequent call to this function from the thread returns the same
................................................................................
      keyInit = 1;
    }
    sqlite3Os.xLeaveMutex();
  }

  pTsd = (SqliteTsd *)pthread_getspecific(key);
  if( !pTsd ){
    pTsd = sqlite3Os.xMalloc(sizeof(SqliteTsd));
    if( pTsd ){
      memset(pTsd, 0, sizeof(SqliteTsd));
      pthread_setspecific(key, pTsd);
    }
  }
  return pTsd;
#else
  static char tsd[sizeof(SqliteTsd)];
  static int isInit = 0;
  assert( nByte==sizeof(SqliteTsd) );
  if( !isInit ){
    memset(tsd, 0, sizeof(SqliteTsd));
    isInit = 1;
  }
  return (void *)tsd;
#endif
................................................................................
  IF_DISKIO( unixSyncDirectory ),
  IF_DISKIO( unixTempFileName ),
  unixRandomSeed,
  unixSleep,
  unixCurrentTime,
  unixEnterMutex,
  unixLeaveMutex,
  unixThreadSpecificData,
  genericMalloc,
  genericRealloc,
  genericFree,
  genericAllocationSize
};



#endif /* OS_UNIX */

Changes to src/os_win.c.

1058
1059
1060
1061
1062
1063
1064
1065




1066
1067
1068
  IF_DISKIO( winSyncDirectory ),
  IF_DISKIO( winTempFileName ),
  winRandomSeed,
  winSleep,
  winCurrentTime,
  winEnterMutex,
  winLeaveMutex,
  winThreadSpecificData




};

#endif /* OS_WIN */







|
>
>
>
>



1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
  IF_DISKIO( winSyncDirectory ),
  IF_DISKIO( winTempFileName ),
  winRandomSeed,
  winSleep,
  winCurrentTime,
  winEnterMutex,
  winLeaveMutex,
  winThreadSpecificData,
  genericMalloc,
  genericRealloc,
  genericFree,
  genericAllocationSize
};

#endif /* OS_WIN */

Changes to src/util.c.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
..
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
..
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
...
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
...
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
...
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
...
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
...
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
...
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
...
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
**
*************************************************************************
** Utility functions used throughout sqlite.
**
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
** $Id: util.c,v 1.153 2005/12/15 10:11:32 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <stdarg.h>
#include <ctype.h>

/*
................................................................................
** The function sqlite3FreeX performs the same task as sqlite3Free and is
** guaranteed to be a real function.
**
** The above APIs are implemented in terms of the functions provided at the Os
** level (not in this file). The Os level interface is never accessed directly
** by code outside of this file.
**
**     sqlite3OsMalloc()
**     sqlite3OsRealloc()
**     sqlite3OsFree()
**     sqlite3OsAllocationSize()
**
** Functions sqlite3MallocRaw() and sqlite3Realloc() may invoke 
** sqlite3_release_memory() if a call to sqlite3OsMalloc() or
** sqlite3OsRealloc() fails. Function sqlite3Malloc() usually invokes
** sqlite3MallocRaw().
**
** MALLOC TEST WRAPPER ARCHITECTURE
**
** The test wrapper provides extra test facilities to ensure the library 
** does not leak memory and handles the failure of the underlying (Os level)
** allocation system correctly. It is only present if the library is 
................................................................................
** compiled with the SQLITE_MEMDEBUG macro set.
**
**     * Guardposts to detect overwrites.
**     * Ability to cause a specific Malloc() or Realloc() to fail.
**     * Audit outstanding memory allocations (i.e check for leaks).
*/

/*
** sqlite3OsMalloc
** sqlite3OsRealloc
** sqlite3OsOsFree
** sqlite3OsAllocationSize
**
** Implementation of the os level dynamic memory allocation interface in terms
** of the standard malloc(), realloc() and free() found in many operating
** systems. No rocket science here.
*/
void *sqlite3OsMalloc(int n){
  char *p = (char *)malloc(n+8);
  assert(n>0);
  assert(sizeof(int)<=8);
  if( p ){
    *(int *)p = n;
  }
  return (void *)(p + 8);
}
void *sqlite3OsRealloc(void *p, int n){
  char *p2 = ((char *)p - 8);
  assert(n>0);
  p2 = realloc(p2, n+8);
  if( p2 ){
    *(int *)p2 = n;
  }
  return (void *)((char *)p2 + 8);
}
void sqlite3OsFree(void *p){
  assert(p);
  free((void *)((char *)p - 8));
}
int sqlite3OsAllocationSize(void *p){
  return *(int *)((char *)p - 8);
}

/*
** TODO!
*/
#define sqlite3_release_memory(x) 0

#ifdef SQLITE_MEMDEBUG
/*--------------------------------------------------------------------------
................................................................................
*/ 

#define TESTALLOC_OFFSET_GUARD1(p)    (sizeof(void *) * 2)
#define TESTALLOC_OFFSET_DATA(p) ( \
  TESTALLOC_OFFSET_GUARD1(p) + sizeof(u32) * TESTALLOC_NGUARD \
)
#define TESTALLOC_OFFSET_GUARD2(p) ( \
  TESTALLOC_OFFSET_DATA(p) + sqlite3OsAllocationSize(p) - TESTALLOC_OVERHEAD \
)
#define TESTALLOC_OFFSET_LINENUMBER(p) ( \
  TESTALLOC_OFFSET_GUARD2(p) + sizeof(u32) * TESTALLOC_NGUARD \
)
#define TESTALLOC_OFFSET_FILENAME(p) ( \
  TESTALLOC_OFFSET_LINENUMBER(p) + sizeof(u32) \
)
................................................................................
      return 1;
    }
  }
  return 0;
}

/*
** The argument is a pointer returned by sqlite3OsMalloc() or Realloc().
** assert() that the first and last (TESTALLOC_NGUARD*4) bytes are set to the
** values set by the applyGuards() function.
*/
static void checkGuards(u32 *p)
{
  int i;
  char *zAlloc = (char *)p;
................................................................................
    u32 guard = 0;
    memcpy(&guard, &z[i*sizeof(u32)], sizeof(u32));
    assert(guard==0xdead3344);
  }
}

/*
** The argument is a pointer returned by sqlite3OsMalloc() or Realloc(). The
** first and last (TESTALLOC_NGUARD*4) bytes are set to known values for use as 
** guard-posts.
*/
static void applyGuards(u32 *p)
{
  int i;
  char *z;
................................................................................
  Tcl_IncrRefCount(pRes);

  for(p=pTsd->pFirst; p; p=((void **)p)[1]){
    Tcl_Obj *pEntry = Tcl_NewObj();
    Tcl_Obj *pStack = Tcl_NewObj();
    char *z;
    u32 iLine;
    int nBytes = sqlite3OsAllocationSize(p) - TESTALLOC_OVERHEAD;
    char *zAlloc = (char *)p;
    int i;

    Tcl_ListObjAppendElement(0, pEntry, Tcl_NewIntObj(nBytes));

    z = &zAlloc[TESTALLOC_OFFSET_FILENAME(p)];
    Tcl_ListObjAppendElement(0, pEntry, Tcl_NewStringObj(z, -1));
................................................................................
  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){
  if( !failMalloc() ){
    u32 *p;
    p = (u32 *)sqlite3OsMalloc(n + TESTALLOC_OVERHEAD);
    assert(p);
    sqlite3_nMalloc++;
    applyGuards(p);
    linkAlloc(p);
    return (void *)(&p[TESTALLOC_NGUARD + 2*sizeof(void *)/sizeof(u32)]);
  }
  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.
*/
void OSFREE(void *pFree){
  u32 *p = (u32 *)getOsPointer(pFree);   /* p points to Os level allocation */
  checkGuards(p);
  unlinkAlloc(p);
  sqlite3OsFree(p);
  sqlite3_nFree++;
}

/*
** This is the test layer's wrapper around sqlite3OsRealloc().
*/
void * OSREALLOC(void *pRealloc, int n){
  if( !failMalloc() ){
    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;
}

void OSMALLOC_FAILED(){
  sqlite3Tsd()->isFail = 0;
}

int OSSIZEOF(void *p){
  if( p ){
    return sqlite3OsAllocationSize(p) - TESTALLOC_OVERHEAD;
  }
  return 0;
}

#else
#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
/*
** End code for memory allocation system test layer.
**--------------------------------------------------------------------------*/

/*
** The handleSoftLimit() function is called before each call to 
** sqlite3OsMalloc() or sqlite3OsRealloc(). The parameter 'n' is the number of
** extra bytes about to be allocated (for Realloc() this means the size of the
** new allocation less the size of the old allocation). If the extra allocation
** means that the total memory allocated to SQLite in this thread would exceed
** the limit set by sqlite3_soft_heap_limit(), then sqlite3_release_memory() is
** called to try to avoid this. No indication of whether or not this is
** successful is returned to the caller.
**
................................................................................
}
#else
#define handleSoftLimit()
#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){
  SqliteTsd *pTsd = sqlite3Tsd();
  void *p = 0;
  if( n>0 && !pTsd->mallocFailed ){
    handleSoftLimit(n);
................................................................................
      OSMALLOC_FAILED();
    }
  }
  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){
  SqliteTsd *pTsd = sqlite3Tsd();
  if( pTsd->mallocFailed ){
    return 0;







|







 







|
|
|
|


|
|







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







|







 







|







 







|







 







|







 







|




|










|






|




|





|













|





|
|
|
|








|







 







|







 







|







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
..
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
..
58
59
60
61
62
63
64




































65
66
67
68
69
70
71
...
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
...
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
...
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
...
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
...
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
...
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
...
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
**
*************************************************************************
** Utility functions used throughout sqlite.
**
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
** $Id: util.c,v 1.154 2005/12/15 10:50:54 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <stdarg.h>
#include <ctype.h>

/*
................................................................................
** The function sqlite3FreeX performs the same task as sqlite3Free and is
** guaranteed to be a real function.
**
** The above APIs are implemented in terms of the functions provided at the Os
** level (not in this file). The Os level interface is never accessed directly
** by code outside of this file.
**
**     sqlite3Os.xMalloc()
**     sqlite3Os.xRealloc()
**     sqlite3Os.xFree()
**     sqlite3Os.xAllocationSize()
**
** Functions sqlite3MallocRaw() and sqlite3Realloc() may invoke 
** sqlite3_release_memory() if a call to sqlite3Os.xMalloc() or
** sqlite3Os.xRealloc() fails. Function sqlite3Malloc() usually invokes
** sqlite3MallocRaw().
**
** MALLOC TEST WRAPPER ARCHITECTURE
**
** The test wrapper provides extra test facilities to ensure the library 
** does not leak memory and handles the failure of the underlying (Os level)
** allocation system correctly. It is only present if the library is 
................................................................................
** compiled with the SQLITE_MEMDEBUG macro set.
**
**     * Guardposts to detect overwrites.
**     * Ability to cause a specific Malloc() or Realloc() to fail.
**     * Audit outstanding memory allocations (i.e check for leaks).
*/





































/*
** TODO!
*/
#define sqlite3_release_memory(x) 0

#ifdef SQLITE_MEMDEBUG
/*--------------------------------------------------------------------------
................................................................................
*/ 

#define TESTALLOC_OFFSET_GUARD1(p)    (sizeof(void *) * 2)
#define TESTALLOC_OFFSET_DATA(p) ( \
  TESTALLOC_OFFSET_GUARD1(p) + sizeof(u32) * TESTALLOC_NGUARD \
)
#define TESTALLOC_OFFSET_GUARD2(p) ( \
  TESTALLOC_OFFSET_DATA(p) + sqlite3Os.xAllocationSize(p) - TESTALLOC_OVERHEAD \
)
#define TESTALLOC_OFFSET_LINENUMBER(p) ( \
  TESTALLOC_OFFSET_GUARD2(p) + sizeof(u32) * TESTALLOC_NGUARD \
)
#define TESTALLOC_OFFSET_FILENAME(p) ( \
  TESTALLOC_OFFSET_LINENUMBER(p) + sizeof(u32) \
)
................................................................................
      return 1;
    }
  }
  return 0;
}

/*
** The argument is a pointer returned by sqlite3Os.xMalloc() or xRealloc().
** assert() that the first and last (TESTALLOC_NGUARD*4) bytes are set to the
** values set by the applyGuards() function.
*/
static void checkGuards(u32 *p)
{
  int i;
  char *zAlloc = (char *)p;
................................................................................
    u32 guard = 0;
    memcpy(&guard, &z[i*sizeof(u32)], sizeof(u32));
    assert(guard==0xdead3344);
  }
}

/*
** The argument is a pointer returned by sqlite3Os.xMalloc() or Realloc(). The
** first and last (TESTALLOC_NGUARD*4) bytes are set to known values for use as 
** guard-posts.
*/
static void applyGuards(u32 *p)
{
  int i;
  char *z;
................................................................................
  Tcl_IncrRefCount(pRes);

  for(p=pTsd->pFirst; p; p=((void **)p)[1]){
    Tcl_Obj *pEntry = Tcl_NewObj();
    Tcl_Obj *pStack = Tcl_NewObj();
    char *z;
    u32 iLine;
    int nBytes = sqlite3Os.xAllocationSize(p) - TESTALLOC_OVERHEAD;
    char *zAlloc = (char *)p;
    int i;

    Tcl_ListObjAppendElement(0, pEntry, Tcl_NewIntObj(nBytes));

    z = &zAlloc[TESTALLOC_OFFSET_FILENAME(p)];
    Tcl_ListObjAppendElement(0, pEntry, Tcl_NewStringObj(z, -1));
................................................................................
  Tcl_SetObjResult(interp, pRes);
  Tcl_DecrRefCount(pRes);
  return TCL_OK;
}
#endif

/*
** This is the test layer's wrapper around sqlite3Os.xMalloc().
*/
static void * OSMALLOC(int n){
  if( !failMalloc() ){
    u32 *p;
    p = (u32 *)sqlite3Os.xMalloc(n + TESTALLOC_OVERHEAD);
    assert(p);
    sqlite3_nMalloc++;
    applyGuards(p);
    linkAlloc(p);
    return (void *)(&p[TESTALLOC_NGUARD + 2*sizeof(void *)/sizeof(u32)]);
  }
  return 0;
}

/*
** This is the test layer's wrapper around sqlite3Os.xFree(). The argument is a
** pointer to the space allocated for the application to use.
*/
void OSFREE(void *pFree){
  u32 *p = (u32 *)getOsPointer(pFree);   /* p points to Os level allocation */
  checkGuards(p);
  unlinkAlloc(p);
  sqlite3Os.xFree(p);
  sqlite3_nFree++;
}

/*
** This is the test layer's wrapper around sqlite3Os.xRealloc().
*/
void * OSREALLOC(void *pRealloc, int n){
  if( !failMalloc() ){
    u32 *p = (u32 *)getOsPointer(pRealloc);
    checkGuards(p);
    p = sqlite3Os.xRealloc(p, n + TESTALLOC_OVERHEAD);
    applyGuards(p);
    relinkAlloc(p);
    return (void *)(&p[TESTALLOC_NGUARD + 2*sizeof(void *)/sizeof(u32)]);
  }
  return 0;
}

void OSMALLOC_FAILED(){
  sqlite3Tsd()->isFail = 0;
}

int OSSIZEOF(void *p){
  if( p ){
    return sqlite3Os.xAllocationSize(p) - TESTALLOC_OVERHEAD;
  }
  return 0;
}

#else
#define OSMALLOC(x) sqlite3Os.xMalloc(x)
#define OSREALLOC(x,y) sqlite3Os.xRealloc(x,y)
#define OSFREE(x) sqlite3Os.xFree(x)
#define OSSIZEOF(x) sqlite3Os.xAllocationSize(x)
#define OSMALLOC_FAILED()
#endif
/*
** End code for memory allocation system test layer.
**--------------------------------------------------------------------------*/

/*
** The handleSoftLimit() function is called before each call to 
** sqlite3Os.xMalloc() or xRealloc(). The parameter 'n' is the number of
** extra bytes about to be allocated (for Realloc() this means the size of the
** new allocation less the size of the old allocation). If the extra allocation
** means that the total memory allocated to SQLite in this thread would exceed
** the limit set by sqlite3_soft_heap_limit(), then sqlite3_release_memory() is
** called to try to avoid this. No indication of whether or not this is
** successful is returned to the caller.
**
................................................................................
}
#else
#define handleSoftLimit()
#endif

/*
** Allocate and return N bytes of uninitialised memory by calling
** sqlite3Os.xMalloc(). If the Malloc() call fails, attempt to free memory 
** by calling sqlite3_release_memory().
*/
void *sqlite3MallocRaw(int n){
  SqliteTsd *pTsd = sqlite3Tsd();
  void *p = 0;
  if( n>0 && !pTsd->mallocFailed ){
    handleSoftLimit(n);
................................................................................
      OSMALLOC_FAILED();
    }
  }
  return p;
}

/*
** Resize the allocation at p to n bytes by calling sqlite3Os.xRealloc(). 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){
  SqliteTsd *pTsd = sqlite3Tsd();
  if( pTsd->mallocFailed ){
    return 0;