xref: /sqlite-3.40.0/ext/misc/memtrace.c (revision d46b6f57)
1 /*
2 ** 2019-01-21
3 **
4 ** The author disclaims copyright to this source code.  In place of
5 ** a legal notice, here is a blessing:
6 **
7 **    May you do good and not evil.
8 **    May you find forgiveness for yourself and forgive others.
9 **    May you share freely, never taking more than you give.
10 **
11 *************************************************************************
12 **
13 ** This file implements an extension that uses the SQLITE_CONFIG_MALLOC
14 ** mechanism to add a tracing layer on top of SQLite.  If this extension
15 ** is registered prior to sqlite3_initialize(), it will cause all memory
16 ** allocation activities to be logged on standard output, or to some other
17 ** FILE specified by the initializer.
18 **
19 ** This file needs to be compiled into the application that uses it.
20 **
21 ** This extension is used to implement the --memtrace option of the
22 ** command-line shell.
23 */
24 #include <assert.h>
25 #include <string.h>
26 #include <stdio.h>
27 
28 /* The original memory allocation routines */
29 static sqlite3_mem_methods memtraceBase;
30 static FILE *memtraceOut;
31 
32 /* Methods that trace memory allocations */
memtraceMalloc(int n)33 static void *memtraceMalloc(int n){
34   if( memtraceOut ){
35     fprintf(memtraceOut, "MEMTRACE: allocate %d bytes\n",
36             memtraceBase.xRoundup(n));
37   }
38   return memtraceBase.xMalloc(n);
39 }
memtraceFree(void * p)40 static void memtraceFree(void *p){
41   if( p==0 ) return;
42   if( memtraceOut ){
43     fprintf(memtraceOut, "MEMTRACE: free %d bytes\n", memtraceBase.xSize(p));
44   }
45   memtraceBase.xFree(p);
46 }
memtraceRealloc(void * p,int n)47 static void *memtraceRealloc(void *p, int n){
48   if( p==0 ) return memtraceMalloc(n);
49   if( n==0 ){
50     memtraceFree(p);
51     return 0;
52   }
53   if( memtraceOut ){
54     fprintf(memtraceOut, "MEMTRACE: resize %d -> %d bytes\n",
55             memtraceBase.xSize(p), memtraceBase.xRoundup(n));
56   }
57   return memtraceBase.xRealloc(p, n);
58 }
memtraceSize(void * p)59 static int memtraceSize(void *p){
60   return memtraceBase.xSize(p);
61 }
memtraceRoundup(int n)62 static int memtraceRoundup(int n){
63   return memtraceBase.xRoundup(n);
64 }
memtraceInit(void * p)65 static int memtraceInit(void *p){
66   return memtraceBase.xInit(p);
67 }
memtraceShutdown(void * p)68 static void memtraceShutdown(void *p){
69   memtraceBase.xShutdown(p);
70 }
71 
72 /* The substitute memory allocator */
73 static sqlite3_mem_methods ersaztMethods = {
74   memtraceMalloc,
75   memtraceFree,
76   memtraceRealloc,
77   memtraceSize,
78   memtraceRoundup,
79   memtraceInit,
80   memtraceShutdown,
81   0
82 };
83 
84 /* Begin tracing memory allocations to out. */
sqlite3MemTraceActivate(FILE * out)85 int sqlite3MemTraceActivate(FILE *out){
86   int rc = SQLITE_OK;
87   if( memtraceBase.xMalloc==0 ){
88     rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memtraceBase);
89     if( rc==SQLITE_OK ){
90       rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &ersaztMethods);
91     }
92   }
93   memtraceOut = out;
94   return rc;
95 }
96 
97 /* Deactivate memory tracing */
sqlite3MemTraceDeactivate(void)98 int sqlite3MemTraceDeactivate(void){
99   int rc = SQLITE_OK;
100   if( memtraceBase.xMalloc!=0 ){
101     rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memtraceBase);
102     if( rc==SQLITE_OK ){
103       memset(&memtraceBase, 0, sizeof(memtraceBase));
104     }
105   }
106   memtraceOut = 0;
107   return rc;
108 }
109