96 lines
2.7 KiB
C
96 lines
2.7 KiB
C
|
size_t dlmalloc_usable_size(void*); // __ANDROID_API__
|
||
|
|
||
|
#if is(bsd) || is(osx) // bsd or osx
|
||
|
# include <malloc/malloc.h>
|
||
|
#else
|
||
|
# include <malloc.h>
|
||
|
#endif
|
||
|
|
||
|
#ifndef SYS_REALLOC
|
||
|
#define SYS_REALLOC realloc
|
||
|
#define SYS_MSIZE /* bsd/osx, then win32, then ems/__GLIBC__, then __ANDROID_API__ */ \
|
||
|
ifdef(osx, malloc_size, ifdef(bsd, malloc_size, \
|
||
|
ifdef(win32, _msize, malloc_usable_size)))
|
||
|
#endif
|
||
|
|
||
|
// xrealloc --------------------------------------------------------------------
|
||
|
|
||
|
static __thread uint64_t xstats_current = 0, xstats_total = 0;
|
||
|
|
||
|
void* xrealloc(void* oldptr, size_t size) {
|
||
|
// for stats
|
||
|
size_t oldsize = xsize(oldptr);
|
||
|
|
||
|
void *ptr = SYS_REALLOC(oldptr, size);
|
||
|
if( !ptr && size ) {
|
||
|
PANIC("Not memory enough (trying to allocate %u bytes)", (unsigned)size);
|
||
|
}
|
||
|
#if ENABLE_MEMORY_POISON
|
||
|
if( !oldptr && size ) {
|
||
|
memset(ptr, 0xCD, size);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
// for stats
|
||
|
if( oldptr ) {
|
||
|
xstats_current += (int64_t)size - (int64_t)oldsize;
|
||
|
} else {
|
||
|
xstats_current += size;
|
||
|
}
|
||
|
if( xstats_current > xstats_total ) {
|
||
|
xstats_total = xstats_current;
|
||
|
}
|
||
|
|
||
|
return ptr;
|
||
|
}
|
||
|
size_t xsize(void* p) {
|
||
|
if( p ) return SYS_MSIZE(p);
|
||
|
return 0;
|
||
|
}
|
||
|
char *xstats(void) {
|
||
|
return va("%03u/%03uMB", (unsigned)xstats_current / 1024 / 1024, (unsigned)xstats_total / 1024 / 1024);
|
||
|
}
|
||
|
|
||
|
// stack -----------------------------------------------------------------------
|
||
|
|
||
|
void* stack(int bytes) { // use negative bytes to rewind stack
|
||
|
static __thread uint8_t *stack_mem = 0;
|
||
|
static __thread uint64_t stack_ptr = 0;
|
||
|
static __thread uint64_t stack_max = 0; // watch this var, in case you want to fine tune 4 MiB value below
|
||
|
if( bytes < 0 ) {
|
||
|
if( stack_ptr > stack_max ) stack_max = stack_ptr;
|
||
|
return (stack_ptr = 0), NULL;
|
||
|
}
|
||
|
if( !stack_mem ) stack_mem = xrealloc(stack_mem, xsize(stack_mem) + 4 * 1024 * 1024);
|
||
|
return &stack_mem[ (stack_ptr += bytes) - bytes ];
|
||
|
}
|
||
|
|
||
|
// leaks ----------------------------------------------------------------------
|
||
|
|
||
|
void* watch( void *ptr, int sz ) {
|
||
|
static __thread int open = 1;
|
||
|
if( ptr && open ) {
|
||
|
open = 0;
|
||
|
|
||
|
char buf[256];
|
||
|
sprintf(buf, "%p.mem", ptr);
|
||
|
for( FILE *fp = fopen(buf, "a+"); fp; fclose(fp), fp = 0 ) {
|
||
|
fseek(fp, 0L, SEEK_END);
|
||
|
const char *cs = callstack( +16 ); // +48
|
||
|
fprintf(fp, "Built %s %s\n", __DATE__, __TIME__); // today() instead?
|
||
|
fprintf(fp, "Memleak address: [%p], size: %d\n%s\n", ptr, sz, cs ? cs : "No callstack.");
|
||
|
}
|
||
|
|
||
|
open = 1;
|
||
|
}
|
||
|
return ptr;
|
||
|
}
|
||
|
void* forget( void *ptr ) {
|
||
|
if( ptr ) {
|
||
|
char buf[256];
|
||
|
sprintf(buf, "%p.mem", ptr);
|
||
|
unlink(buf);
|
||
|
}
|
||
|
return ptr;
|
||
|
}
|