| // stb_leakcheck.h - v0.6 - quick & dirty malloc leak-checking - public domain |
| // LICENSE |
| // |
| // See end of file. |
| |
| #ifdef STB_LEAKCHECK_IMPLEMENTATION |
| #undef STB_LEAKCHECK_IMPLEMENTATION // don't implement more than once |
| |
| // if we've already included leakcheck before, undefine the macros |
| #ifdef malloc |
| #undef malloc |
| #undef free |
| #undef realloc |
| #endif |
| |
| #ifndef STB_LEAKCHECK_OUTPUT_PIPE |
| #define STB_LEAKCHECK_OUTPUT_PIPE stdout |
| #endif |
| |
| #include <assert.h> |
| #include <string.h> |
| #include <stdlib.h> |
| #include <stdio.h> |
| #include <stddef.h> |
| typedef struct malloc_info stb_leakcheck_malloc_info; |
| |
| struct malloc_info |
| { |
| const 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, const char *file, int line) |
| { |
| stb_leakcheck_malloc_info *mi = (stb_leakcheck_malloc_info *) 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; |
| free(mi); |
| #endif |
| } |
| } |
| |
| void *stb_leakcheck_realloc(void *ptr, size_t sz, const 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; |
| } |
| } |
| } |
| |
| static void stblkck_internal_print(const char *reason, stb_leakcheck_malloc_info *mi) |
| { |
| #if defined(_MSC_VER) && _MSC_VER < 1900 // 1900=VS 2015 |
| // Compilers that use the old MS C runtime library don't have %zd |
| // and the older ones don't even have %lld either... however, the old compilers |
| // without "long long" don't support 64-bit targets either, so here's the |
| // compromise: |
| #if _MSC_VER < 1400 // before VS 2005 |
| fprintf(STB_LEAKCHECK_OUTPUT_PIPE, "%s: %s (%4d): %8d bytes at %p\n", reason, mi->file, mi->line, (int)mi->size, (void*)(mi+1)); |
| #else |
| fprintf(STB_LEAKCHECK_OUTPUT_PIPE, "%s: %s (%4d): %16lld bytes at %p\n", reason, mi->file, mi->line, (long long)mi->size, (void*)(mi+1)); |
| #endif |
| #else |
| // Assume we have %zd on other targets. |
| #ifdef __MINGW32__ |
| __mingw_fprintf(STB_LEAKCHECK_OUTPUT_PIPE, "%s: %s (%4d): %zd bytes at %p\n", reason, mi->file, mi->line, mi->size, (void*)(mi+1)); |
| #else |
| fprintf(STB_LEAKCHECK_OUTPUT_PIPE, "%s: %s (%4d): %zd bytes at %p\n", reason, mi->file, mi->line, mi->size, (void*)(mi+1)); |
| #endif |
| #endif |
| } |
| |
| void stb_leakcheck_dumpmem(void) |
| { |
| stb_leakcheck_malloc_info *mi = mi_head; |
| while (mi) { |
| if ((ptrdiff_t) mi->size >= 0) |
| stblkck_internal_print("LEAKED", mi); |
| mi = mi->next; |
| } |
| #ifdef STB_LEAKCHECK_SHOWALL |
| mi = mi_head; |
| while (mi) { |
| if ((ptrdiff_t) mi->size < 0) |
| stblkck_internal_print("FREED ", mi); |
| mi = mi->next; |
| } |
| #endif |
| } |
| #endif // STB_LEAKCHECK_IMPLEMENTATION |
| |
| #if !defined(INCLUDE_STB_LEAKCHECK_H) || !defined(malloc) |
| #define INCLUDE_STB_LEAKCHECK_H |
| |
| #include <stdlib.h> // we want to define the macros *after* stdlib to avoid a slew of errors |
| |
| #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, const char *file, int line); |
| extern void * stb_leakcheck_realloc(void *ptr, size_t sz, const char *file, int line); |
| extern void stb_leakcheck_free(void *ptr); |
| extern void stb_leakcheck_dumpmem(void); |
| |
| #endif // INCLUDE_STB_LEAKCHECK_H |
| |
| |
| /* |
| ------------------------------------------------------------------------------ |
| This software is available under 2 licenses -- choose whichever you prefer. |
| ------------------------------------------------------------------------------ |
| ALTERNATIVE A - MIT License |
| Copyright (c) 2017 Sean Barrett |
| Permission is hereby granted, free of charge, to any person obtaining a copy of |
| this software and associated documentation files (the "Software"), to deal in |
| the Software without restriction, including without limitation the rights to |
| use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies |
| of the Software, and to permit persons to whom the Software is furnished to do |
| so, subject to the following conditions: |
| The above copyright notice and this permission notice shall be included in all |
| copies or substantial portions of the Software. |
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| SOFTWARE. |
| ------------------------------------------------------------------------------ |
| ALTERNATIVE B - Public Domain (www.unlicense.org) |
| This is free and unencumbered software released into the public domain. |
| Anyone is free to copy, modify, publish, use, compile, sell, or distribute this |
| software, either in source code form or as a compiled binary, for any purpose, |
| commercial or non-commercial, and by any means. |
| In jurisdictions that recognize copyright laws, the author or authors of this |
| software dedicate any and all copyright interest in the software to the public |
| domain. We make this dedication for the benefit of the public at large and to |
| the detriment of our heirs and successors. We intend this dedication to be an |
| overt act of relinquishment in perpetuity of all present and future rights to |
| this software under copyright law. |
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
| ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
| WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| ------------------------------------------------------------------------------ |
| */ |