From 0d840ab3303aa645ae09dc9338a931fce754a8b5 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Wed, 21 Jan 2015 07:46:54 -0800 Subject: [PATCH] quick & dirty leak checker --- stb_leakcheck.h | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++++ stb_vorbis.c | 7 ++++ tests/stb.dsp | 8 ++++ tests/test_vorbis.c | 18 ++++++++ 4 files changed, 150 insertions(+) create mode 100644 stb_leakcheck.h create mode 100644 tests/test_vorbis.c diff --git a/stb_leakcheck.h b/stb_leakcheck.h new file mode 100644 index 0000000..d309da5 --- /dev/null +++ b/stb_leakcheck.h @@ -0,0 +1,117 @@ +// stb_leakcheck.h - v0.1 - quick & dirty malloc leak-checking - public domain + +#ifdef STB_LEAKCHECK_IMPLEMENTATION +#undef STB_LEAKCHECK_IMPLEMENTATION // don't implenment more than once + +// if we've already included leakcheck before, undefine the macros +#ifdef malloc +#undef malloc +#undef free +#undef realloc +#endif + +#include +#include +#include +typedef struct malloc_info stb_leakcheck_malloc_info; + +struct malloc_info +{ + char *file; + int line; + size_t size; + stb_leakcheck_malloc_info *next,*prev; +}; + +static stb_leakcheck_malloc_info *mi_head; + +void *stb_leakcheck_malloc(size_t sz, char *file, int line) +{ + stb_leakcheck_malloc_info *mi = malloc(sz + sizeof(*mi)); + if (mi == NULL) return mi; + mi->file = file; + mi->line = line; + mi->next = mi_head; + if (mi_head) + mi->next->prev = mi; + mi->prev = NULL; + mi->size = (int) sz; + mi_head = mi; + return mi+1; +} + +void stb_leakcheck_free(void *ptr) +{ + if (ptr != NULL) { + stb_leakcheck_malloc_info *mi = (stb_leakcheck_malloc_info *) ptr - 1; + mi->size = ~mi->size; + #ifndef STB_LEAKCHECK_SHOWALL + if (mi->prev == NULL) { + assert(mi_head == mi); + mi_head = mi->next; + } else + mi->prev->next = mi->next; + if (mi->next) + mi->next->prev = mi->prev; + #endif + } +} + +void *stb_leakcheck_realloc(void *ptr, size_t sz, char *file, int line) +{ + if (ptr == NULL) { + return stb_leakcheck_malloc(sz, file, line); + } else if (sz == 0) { + stb_leakcheck_free(ptr); + return NULL; + } else { + stb_leakcheck_malloc_info *mi = (stb_leakcheck_malloc_info *) ptr - 1; + if (sz <= mi->size) + return ptr; + else { + #ifdef STB_LEAKCHECK_REALLOC_PRESERVE_MALLOC_FILELINE + void *q = stb_leakcheck_malloc(sz, mi->file, mi->line); + #else + void *q = stb_leakcheck_malloc(sz, file, line); + #endif + if (q) { + memcpy(q, ptr, mi->size); + stb_leakcheck_free(ptr); + } + return q; + } + } +} + +void stb_leakcheck_dumpmem(void) +{ + stb_leakcheck_malloc_info *mi = mi_head; + while (mi) { + if ((ptrdiff_t) mi->size >= 0) + printf("LEAKED: %s (%4d): %8z bytes at %p\n", mi->file, mi->line, mi->size, mi+1); + mi = mi->next; + } + #ifdef STB_LEAKCHECK_SHOWALL + mi = mi_head; + while (mi) { + if ((ptrdiff_t) mi->size < 0) + printf("FREED : %s (%4d): %8z bytes at %p\n", mi->file, mi->line, ~mi->size, mi+1); + mi = mi->next; + } + #endif +} +#endif // STB_LEAKCHECK_IMPLEMENTATION + +#ifndef INCLUDE_STB_LEAKCHECK_H +#define INCLUDE_STB_LEAKCHECK_H + +#define malloc(sz) stb_leakcheck_malloc(sz, __FILE__, __LINE__) +#define free(p) stb_leakcheck_free(p) +#define realloc(p,sz) stb_leakcheck_realloc(p,sz, __FILE__, __LINE__) + +extern void * stb_leakcheck_malloc(size_t sz, char *file, int line); +extern void * stb_leakcheck_realloc(void *ptr, size_t sz, char *file, int line); +extern void stb_leakcheck_free(void *ptr); +extern void stb_leakcheck_dumpmem(void); + +#endif // INCLUDE_STB_LEAKCHECK_H diff --git a/stb_vorbis.c b/stb_vorbis.c index ef346fc..99ef0d7 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -327,6 +327,8 @@ extern int stb_vorbis_get_samples_short(stb_vorbis *f, int channels, short **buf #endif +extern void stb_vorbis_free(void *p); + //////// ERROR CODES enum STBVorbisError @@ -592,6 +594,11 @@ typedef float codetype; typedef uint16 codetype; #endif +//#define STB_LEAKCHECK_IMPLEMENTATION +//#define STB_LEAKCHECK_SHOWALL +//#include "stb_leakcheck.h" +//void stb_vorbis_dumpmem(void) { stb_leakcheck_dumpmem(); } + // @NOTE // // Some arrays below are tagged "//varies", which means it's actually diff --git a/tests/stb.dsp b/tests/stb.dsp index 3d642a1..b86c6d2 100644 --- a/tests/stb.dsp +++ b/tests/stb.dsp @@ -122,6 +122,10 @@ SOURCE=..\stb_image_write.h # End Source File # Begin Source File +SOURCE=..\stb_leakcheck.h +# End Source File +# Begin Source File + SOURCE=..\stb_perlin.h # End Source File # Begin Source File @@ -162,6 +166,10 @@ SOURCE=.\test_truetype.c # End Source File # Begin Source File +SOURCE=.\test_vorbis.c +# End Source File +# Begin Source File + SOURCE=.\textedit_sample.c # End Source File # End Target diff --git a/tests/test_vorbis.c b/tests/test_vorbis.c new file mode 100644 index 0000000..a9a9f26 --- /dev/null +++ b/tests/test_vorbis.c @@ -0,0 +1,18 @@ +#define STB_VORBIS_HEADER_ONLY +#include "stb_vorbis.c" +#include "stb.h" + +extern void stb_vorbis_dumpmem(void); + +#ifdef VORBIS_TEST +int main(int argc, char **argv) +{ + size_t memlen; + unsigned char *mem = stb_fileu("c:/x/01.ogg", &memlen); + int chan, samplerate; + short *output; + int samples = stb_vorbis_decode_memory(mem, memlen, &chan, &samplerate, &output); + stb_vorbis_dumpmem(); + return 0; +} +#endif