/ Check-in [d55a5e1c]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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

Overview
Comment:Add the ability to simulate out-of-memory errors when using the default memory allocator, mem1.c. Fix a bug that this enhancement revealed. (CVS 4875)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: d55a5e1c11ef90534abd2e5f18d06dd4739ade70
User & Date: drh 2008-03-18 00:07:11
Context
2008-03-18
00:54
Fix a memory leak introduced by the previous bug fix. (CVS 4876) check-in: b9c5dce3 user: drh tags: trunk
00:07
Add the ability to simulate out-of-memory errors when using the default memory allocator, mem1.c. Fix a bug that this enhancement revealed. (CVS 4875) check-in: d55a5e1c user: drh tags: trunk
2008-03-17
19:03
Version 3.5.7 (CVS 4874) check-in: 9a6583d3 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/mem1.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
133
134
135
136
137
138
139



140
141
142
143

144
145
146
147
148
149
150
...
201
202
203
204
205
206
207



208
209
210
211
212
213

214
215
216
217
218
219
220
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains the C functions that implement a memory
** allocation subsystem for use by SQLite.  
**
** $Id: mem1.c,v 1.16 2008/02/14 23:26:56 drh Exp $
*/
#include "sqliteInt.h"

/*
** This version of the memory allocator is the default.  It is
** used when no other memory allocator is specified using compile-time
** macros.
................................................................................
void *sqlite3_malloc(int nBytes){
  sqlite3_int64 *p = 0;
  if( nBytes>0 ){
    enterMem();
    if( mem.alarmCallback!=0 && mem.nowUsed+nBytes>=mem.alarmThreshold ){
      sqlite3MemsysAlarm(nBytes);
    }



    p = malloc(nBytes+8);
    if( p==0 ){
      sqlite3MemsysAlarm(nBytes);
      p = malloc(nBytes+8);

    }
    if( p ){
      p[0] = nBytes;
      p++;
      mem.nowUsed += nBytes;
      if( mem.nowUsed>mem.mxUsed ){
        mem.mxUsed = mem.nowUsed;
................................................................................
  p--;
  nOld = (int)p[0];
  assert( mem.mutex!=0 );
  sqlite3_mutex_enter(mem.mutex);
  if( mem.nowUsed+nBytes-nOld>=mem.alarmThreshold ){
    sqlite3MemsysAlarm(nBytes-nOld);
  }



  p = realloc(p, nBytes+8);
  if( p==0 ){
    sqlite3MemsysAlarm(nBytes);
    p = pPrior;
    p--;
    p = realloc(p, nBytes+8);

  }
  if( p ){
    p[0] = nBytes;
    p++;
    mem.nowUsed += nBytes-nOld;
    if( mem.nowUsed>mem.mxUsed ){
      mem.mxUsed = mem.nowUsed;







|







 







>
>
>
|
|
|
|
>







 







>
>
>
|
|
|
|
|
|
>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
...
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains the C functions that implement a memory
** allocation subsystem for use by SQLite.  
**
** $Id: mem1.c,v 1.17 2008/03/18 00:07:11 drh Exp $
*/
#include "sqliteInt.h"

/*
** This version of the memory allocator is the default.  It is
** used when no other memory allocator is specified using compile-time
** macros.
................................................................................
void *sqlite3_malloc(int nBytes){
  sqlite3_int64 *p = 0;
  if( nBytes>0 ){
    enterMem();
    if( mem.alarmCallback!=0 && mem.nowUsed+nBytes>=mem.alarmThreshold ){
      sqlite3MemsysAlarm(nBytes);
    }
    if( sqlite3FaultStep(SQLITE_FAULTINJECTOR_MALLOC) ){
      p = 0;
    }else{
      p = malloc(nBytes+8);
      if( p==0 ){
        sqlite3MemsysAlarm(nBytes);
        p = malloc(nBytes+8);
      }
    }
    if( p ){
      p[0] = nBytes;
      p++;
      mem.nowUsed += nBytes;
      if( mem.nowUsed>mem.mxUsed ){
        mem.mxUsed = mem.nowUsed;
................................................................................
  p--;
  nOld = (int)p[0];
  assert( mem.mutex!=0 );
  sqlite3_mutex_enter(mem.mutex);
  if( mem.nowUsed+nBytes-nOld>=mem.alarmThreshold ){
    sqlite3MemsysAlarm(nBytes-nOld);
  }
  if( sqlite3FaultStep(SQLITE_FAULTINJECTOR_MALLOC) ){
    p = 0;
  }else{
    p = realloc(p, nBytes+8);
    if( p==0 ){
      sqlite3MemsysAlarm(nBytes);
      p = pPrior;
      p--;
      p = realloc(p, nBytes+8);
    }
  }
  if( p ){
    p[0] = nBytes;
    p++;
    mem.nowUsed += nBytes-nOld;
    if( mem.nowUsed>mem.mxUsed ){
      mem.mxUsed = mem.nowUsed;

Changes to src/test_malloc.c.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
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
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file contains code used to implement test interfaces to the
** memory allocation subsystem.
**
** $Id: test_malloc.c,v 1.15 2008/02/19 15:15:16 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>

................................................................................
*/
static int test_memdebug_pending(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){

  if( objc!=1 ){
    Tcl_WrongNumArgs(interp, 1, objv, "");
    return TCL_ERROR;
  }

#if defined(SQLITE_MEMDEBUG) || defined(SQLITE_POW2_MEMORY_SIZE)
  {
    int nPending = sqlite3_test_control(SQLITE_TESTCTRL_FAULT_PENDING,
                                        SQLITE_FAULTINJECTOR_MALLOC);
    Tcl_SetObjResult(interp, Tcl_NewIntObj(nPending));
  }
#endif
  return TCL_OK;
}


/*
** Usage:    sqlite3_memdebug_settitle TITLE
**







|







 







>




<
<
<
|
|
|
<
<







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
459
460
461
462
463
464
465
466
467
468
469
470



471
472
473


474
475
476
477
478
479
480
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file contains code used to implement test interfaces to the
** memory allocation subsystem.
**
** $Id: test_malloc.c,v 1.16 2008/03/18 00:07:11 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>

................................................................................
*/
static int test_memdebug_pending(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  int nPending;
  if( objc!=1 ){
    Tcl_WrongNumArgs(interp, 1, objv, "");
    return TCL_ERROR;
  }



  nPending = sqlite3_test_control(SQLITE_TESTCTRL_FAULT_PENDING,
                                  SQLITE_FAULTINJECTOR_MALLOC);
  Tcl_SetObjResult(interp, Tcl_NewIntObj(nPending));


  return TCL_OK;
}


/*
** Usage:    sqlite3_memdebug_settitle TITLE
**

Changes to src/vdbemem.c.

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

  assert( (f & (MEM_Dyn|MEM_Static|MEM_Ephem))==0 
       || (f & (MEM_Dyn|MEM_Static|MEM_Ephem))==MEM_Dyn 
       || (f & (MEM_Dyn|MEM_Static|MEM_Ephem))==MEM_Ephem 
       || (f & (MEM_Dyn|MEM_Static|MEM_Ephem))==MEM_Static 
  );

  if( ((f&MEM_Dyn)==0 || pMem->xDel || sqlite3MallocSize(pMem->z)<n) ){

    /* Allocate the new buffer. The minimum allocation size is 32 bytes. */
    char *z = 0;
    if( n>0 ){
      if( preserve && (f&MEM_Dyn) && !pMem->xDel ){
        z = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
        pMem->z = 0;
        preserve = 0;
      }else{
        z = sqlite3DbMallocRaw(pMem->db, (n>32?n:32));
      }
      if( !z ){

        return SQLITE_NOMEM;
      }
    }

    /* If the value is currently a string or blob and the preserve flag
    ** is true, copy the content to the new buffer. 
    */







|












>







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

  assert( (f & (MEM_Dyn|MEM_Static|MEM_Ephem))==0 
       || (f & (MEM_Dyn|MEM_Static|MEM_Ephem))==MEM_Dyn 
       || (f & (MEM_Dyn|MEM_Static|MEM_Ephem))==MEM_Ephem 
       || (f & (MEM_Dyn|MEM_Static|MEM_Ephem))==MEM_Static 
  );

  if( (f&MEM_Dyn)==0 || pMem->xDel || sqlite3MallocSize(pMem->z)<n ){

    /* Allocate the new buffer. The minimum allocation size is 32 bytes. */
    char *z = 0;
    if( n>0 ){
      if( preserve && (f&MEM_Dyn) && !pMem->xDel ){
        z = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
        pMem->z = 0;
        preserve = 0;
      }else{
        z = sqlite3DbMallocRaw(pMem->db, (n>32?n:32));
      }
      if( !z ){
        pMem->flags = MEM_Null;
        return SQLITE_NOMEM;
      }
    }

    /* If the value is currently a string or blob and the preserve flag
    ** is true, copy the content to the new buffer. 
    */

Changes to test/malloc_common.tcl.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

24
25
26
27
28
29
30
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file contains common code used by many different malloc tests
# within the test suite.
#
# $Id: malloc_common.tcl,v 1.13 2008/02/18 22:24:58 drh Exp $

# If we did not compile with malloc testing enabled, then do nothing.
#
ifcapable !memdebug&&!mem5 {
  set MEMDEBUG 0
  return 0
} else {
  set MEMDEBUG 1

}

# Usage: do_malloc_test <test number> <options...>
#
# The first argument, <test number>, is an integer used to name the
# tests executed by this proc. Options are as follows:
#







|



|
|
<

|
>







8
9
10
11
12
13
14
15
16
17
18
19
20

21
22
23
24
25
26
27
28
29
30
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file contains common code used by many different malloc tests
# within the test suite.
#
# $Id: malloc_common.tcl,v 1.14 2008/03/18 00:07:11 drh Exp $

# If we did not compile with malloc testing enabled, then do nothing.
#
ifcapable faultinjector {
  set MEMDEBUG 1

} else {
  set MEMDEBUG 0
  return 0
}

# Usage: do_malloc_test <test number> <options...>
#
# The first argument, <test number>, is an integer used to name the
# tests executed by this proc. Options are as follows:
#