Index: Makefile.msc ================================================================== --- Makefile.msc +++ Makefile.msc @@ -50,10 +50,11 @@ # # Use native Win32 heap. # TCC = $(TCC) -DSQLITE_WIN32_MALLOC=1 +# TCC = $(TCC) -DSQLITE_WIN32_MALLOC_VALIDATE=1 # The locations of the Tcl header and library files. Also, the library that # non-stubs enabled programs using Tcl must link against. These variables # (TCLINCDIR, TCLLIBDIR, and LIBTCL) may be overridden via the environment # prior to running nmake in order to match the actual installed location and Index: src/os_win.c ================================================================== --- src/os_win.c +++ src/os_win.c @@ -152,10 +152,13 @@ #define WINMEM_MAGIC 0x42b2830b static struct winMemData win_mem_data = { WINMEM_MAGIC, NULL, FALSE }; +#define winMemAssertMagic() assert( win_mem_data.magic==WINMEM_MAGIC ) +#define winMemGetHeap() win_mem_data.hHeap + static void *winMemMalloc(int nBytes); static void winMemFree(void *pPrior); static void *winMemRealloc(void *pPrior, int nBytes); static int winMemSize(void *p); static int winMemRoundup(int n); @@ -220,74 +223,97 @@ /* ** Allocate nBytes of memory. */ static void *winMemMalloc(int nBytes){ HANDLE hHeap; + void *p; - assert( win_mem_data.magic==WINMEM_MAGIC ); - hHeap = win_mem_data.hHeap; + winMemAssertMagic(); + hHeap = winMemGetHeap(); assert( hHeap!=0 ); assert( hHeap!=INVALID_HANDLE_VALUE ); #ifdef SQLITE_WIN32_MALLOC_VALIDATE assert ( HeapValidate(hHeap, 0, NULL) ); #endif assert( nBytes>=0 ); - return HeapAlloc(hHeap, 0, (SIZE_T)nBytes); + p = HeapAlloc(hHeap, 0, (SIZE_T)nBytes); + if( !p ){ + sqlite3_log(SQLITE_NOMEM, "failed to HeapAlloc %u bytes (%d), heap=%p", + nBytes, GetLastError(), (void*)hHeap); + } + return p; } /* ** Free memory. */ static void winMemFree(void *pPrior){ HANDLE hHeap; - assert( win_mem_data.magic==WINMEM_MAGIC ); - hHeap = win_mem_data.hHeap; + winMemAssertMagic(); + hHeap = winMemGetHeap(); assert( hHeap!=0 ); assert( hHeap!=INVALID_HANDLE_VALUE ); #ifdef SQLITE_WIN32_MALLOC_VALIDATE assert ( HeapValidate(hHeap, 0, pPrior) ); #endif - if (!pPrior) return; /* Passing NULL to HeapFree is undefined. */ - HeapFree(hHeap, 0, pPrior); + if( !pPrior ) return; /* Passing NULL to HeapFree is undefined. */ + if( !HeapFree(hHeap, 0, pPrior) ){ + sqlite3_log(SQLITE_NOMEM, "failed to HeapFree block %p (%d), heap=%p", + pPrior, GetLastError(), (void*)hHeap); + } } /* ** Change the size of an existing memory allocation */ static void *winMemRealloc(void *pPrior, int nBytes){ HANDLE hHeap; + void *p; - assert( win_mem_data.magic==WINMEM_MAGIC ); - hHeap = win_mem_data.hHeap; + winMemAssertMagic(); + hHeap = winMemGetHeap(); assert( hHeap!=0 ); assert( hHeap!=INVALID_HANDLE_VALUE ); #ifdef SQLITE_WIN32_MALLOC_VALIDATE assert ( HeapValidate(hHeap, 0, pPrior) ); #endif assert( nBytes>=0 ); - if (!pPrior) return HeapAlloc(hHeap, 0, (SIZE_T)nBytes); - return HeapReAlloc(hHeap, 0, pPrior, (SIZE_T)nBytes); + if( !pPrior ){ + p = HeapAlloc(hHeap, 0, (SIZE_T)nBytes); + }else{ + p = HeapReAlloc(hHeap, 0, pPrior, (SIZE_T)nBytes); + } + if( !p ){ + sqlite3_log(SQLITE_NOMEM, "failed to %s %u bytes (%d), heap=%p", + pPrior ? "HeapReAlloc" : "HeapAlloc", nBytes, GetLastError(), + (void*)hHeap); + } + return p; } /* ** Return the size of an outstanding allocation, in bytes. */ static int winMemSize(void *p){ HANDLE hHeap; SIZE_T n; - assert( win_mem_data.magic==WINMEM_MAGIC ); - hHeap = win_mem_data.hHeap; + winMemAssertMagic(); + hHeap = winMemGetHeap(); assert( hHeap!=0 ); assert( hHeap!=INVALID_HANDLE_VALUE ); #ifdef SQLITE_WIN32_MALLOC_VALIDATE assert ( HeapValidate(hHeap, 0, NULL) ); #endif - if (!p) return 0; + if( !p ) return 0; n = HeapSize(hHeap, 0, p); - assert( n<=INT_MAX ); + if( n==(SIZE_T)-1 ){ + sqlite3_log(SQLITE_NOMEM, "failed to HeapSize block %p (%d), heap=%p", + p, GetLastError(), (void*)hHeap); + return 0; + } return (int)n; } /* ** Round up a request size to the next valid allocation size. @@ -300,16 +326,20 @@ ** Initialize this module. */ static int winMemInit(void *pAppData){ winMemData *pWinMemData = (winMemData *)pAppData; - if (!pWinMemData) return SQLITE_ERROR; + if( !pWinMemData ) return SQLITE_ERROR; assert( pWinMemData->magic==WINMEM_MAGIC ); - if (!pWinMemData->hHeap){ + if( !pWinMemData->hHeap ){ pWinMemData->hHeap = HeapCreate(0, SQLITE_WIN32_HEAP_INIT_SIZE, SQLITE_WIN32_HEAP_MAX_SIZE); - if (!pWinMemData->hHeap){ + if( !pWinMemData->hHeap ){ + sqlite3_log(SQLITE_NOMEM, + "failed to HeapCreate (%d), initSize=%u, maxSize=%u", + GetLastError(), SQLITE_WIN32_HEAP_INIT_SIZE, + SQLITE_WIN32_HEAP_MAX_SIZE); return SQLITE_NOMEM; } pWinMemData->bOwned = TRUE; } assert( pWinMemData->hHeap!=0 ); @@ -324,19 +354,20 @@ ** Deinitialize this module. */ static void winMemShutdown(void *pAppData){ winMemData *pWinMemData = (winMemData *)pAppData; - if (!pWinMemData) return; - if (pWinMemData->hHeap){ + if( !pWinMemData ) return; + if( pWinMemData->hHeap ){ assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE ); #ifdef SQLITE_WIN32_MALLOC_VALIDATE assert( HeapValidate(pWinMemData->hHeap, 0, NULL) ); #endif - if (pWinMemData->bOwned){ - if (!HeapDestroy(pWinMemData->hHeap)){ - /* TODO: Log this? */ + if( pWinMemData->bOwned ){ + if( !HeapDestroy(pWinMemData->hHeap) ){ + sqlite3_log(SQLITE_NOMEM, "failed to HeapDestroy (%d), heap=%p", + GetLastError(), (void*)pWinMemData->hHeap); } pWinMemData->bOwned = FALSE; } pWinMemData->hHeap = NULL; }