2019-01-21 15:55:03 +01:00
|
|
|
/*
|
|
|
|
** 2019-01-21
|
|
|
|
**
|
|
|
|
** The author disclaims copyright to this source code. In place of
|
|
|
|
** a legal notice, here is a blessing:
|
|
|
|
**
|
|
|
|
** May you do good and not evil.
|
|
|
|
** May you find forgiveness for yourself and forgive others.
|
|
|
|
** May you share freely, never taking more than you give.
|
|
|
|
**
|
|
|
|
*************************************************************************
|
|
|
|
**
|
|
|
|
** This file implements an extension that uses the SQLITE_CONFIG_MALLOC
|
|
|
|
** mechanism to add a tracing layer on top of SQLite. If this extension
|
|
|
|
** is registered prior to sqlite3_initialize(), it will cause all memory
|
|
|
|
** allocation activities to be logged on standard output, or to some other
|
|
|
|
** FILE specified by the initializer.
|
|
|
|
**
|
|
|
|
** This file needs to be compiled into the application that uses it.
|
|
|
|
**
|
|
|
|
** This extension is used to implement the --memtrace option of the
|
|
|
|
** command-line shell.
|
|
|
|
*/
|
|
|
|
#include <assert.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
/* The original memory allocation routines */
|
|
|
|
static sqlite3_mem_methods memtraceBase;
|
|
|
|
static FILE *memtraceOut;
|
|
|
|
|
|
|
|
/* Methods that trace memory allocations */
|
|
|
|
static void *memtraceMalloc(int n){
|
|
|
|
if( memtraceOut ){
|
|
|
|
fprintf(memtraceOut, "MEMTRACE: allocate %d bytes\n",
|
|
|
|
memtraceBase.xRoundup(n));
|
|
|
|
}
|
|
|
|
return memtraceBase.xMalloc(n);
|
|
|
|
}
|
|
|
|
static void memtraceFree(void *p){
|
|
|
|
if( p==0 ) return;
|
|
|
|
if( memtraceOut ){
|
|
|
|
fprintf(memtraceOut, "MEMTRACE: free %d bytes\n", memtraceBase.xSize(p));
|
|
|
|
}
|
|
|
|
memtraceBase.xFree(p);
|
|
|
|
}
|
|
|
|
static void *memtraceRealloc(void *p, int n){
|
|
|
|
if( p==0 ) return memtraceMalloc(n);
|
|
|
|
if( n==0 ){
|
|
|
|
memtraceFree(p);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if( memtraceOut ){
|
|
|
|
fprintf(memtraceOut, "MEMTRACE: resize %d -> %d bytes\n",
|
|
|
|
memtraceBase.xSize(p), memtraceBase.xRoundup(n));
|
|
|
|
}
|
|
|
|
return memtraceBase.xRealloc(p, n);
|
|
|
|
}
|
|
|
|
static int memtraceSize(void *p){
|
|
|
|
return memtraceBase.xSize(p);
|
|
|
|
}
|
|
|
|
static int memtraceRoundup(int n){
|
|
|
|
return memtraceBase.xRoundup(n);
|
|
|
|
}
|
|
|
|
static int memtraceInit(void *p){
|
|
|
|
return memtraceBase.xInit(p);
|
|
|
|
}
|
|
|
|
static void memtraceShutdown(void *p){
|
|
|
|
memtraceBase.xShutdown(p);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The substitute memory allocator */
|
|
|
|
static sqlite3_mem_methods ersaztMethods = {
|
|
|
|
memtraceMalloc,
|
|
|
|
memtraceFree,
|
|
|
|
memtraceRealloc,
|
|
|
|
memtraceSize,
|
|
|
|
memtraceRoundup,
|
|
|
|
memtraceInit,
|
2019-02-05 20:52:39 +01:00
|
|
|
memtraceShutdown,
|
|
|
|
0
|
2019-01-21 15:55:03 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/* Begin tracing memory allocations to out. */
|
|
|
|
int sqlite3MemTraceActivate(FILE *out){
|
|
|
|
int rc = SQLITE_OK;
|
|
|
|
if( memtraceBase.xMalloc==0 ){
|
|
|
|
rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memtraceBase);
|
|
|
|
if( rc==SQLITE_OK ){
|
|
|
|
rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &ersaztMethods);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
memtraceOut = out;
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Deactivate memory tracing */
|
|
|
|
int sqlite3MemTraceDeactivate(void){
|
|
|
|
int rc = SQLITE_OK;
|
|
|
|
if( memtraceBase.xMalloc!=0 ){
|
|
|
|
rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memtraceBase);
|
|
|
|
if( rc==SQLITE_OK ){
|
|
|
|
memset(&memtraceBase, 0, sizeof(memtraceBase));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
memtraceOut = 0;
|
|
|
|
return rc;
|
|
|
|
}
|