Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "AntlerMalloc.h"
- #include "AntlerAtomic.h"
- #include <string.h>
- #if defined(_DEBUG) || defined(DEBUG) || defined(_DEVELOPMENT)
- typedef struct Antler_Malloc_Info
- {
- const char* file;
- int line;
- size_t size;
- size_t index;
- }Antler_Malloc_Info;
- typedef struct AllocVector{
- Antler_Malloc_Info** items;
- size_t capacity;
- size_t count;
- size_t itemSize;
- }AllocVector;
- static AllocVector* vector = NULL;
- static AllocVector* MallocVector_Create(size_t _itemSize, size_t _startCapacity)
- {
- AllocVector* vector = malloc(sizeof(*vector));
- if (vector) {
- vector->capacity = _startCapacity;
- vector->count = 0;
- // vector->mutex = Antler_Mutex_Create();
- vector->itemSize = _itemSize;
- vector->items = malloc(_itemSize*vector->capacity);
- }
- else {
- vector = NULL;
- // out of memory
- }
- return vector;
- }
- static void AllocVector_Resize(AllocVector* _vec, size_t _capacity)
- {
- Antler_Malloc_Info **items = realloc(_vec->items, _vec->itemSize * _capacity);
- if (items) {
- _vec->items = items;
- _vec->capacity = _capacity;
- }
- }
- static void AllocVector_Push(AllocVector* _vec, Antler_Malloc_Info* _item)
- {
- if (_vec->capacity == _vec->count)
- AllocVector_Resize(_vec, _vec->capacity * 2);
- _vec->items[_vec->count++] = _item;
- }
- static void AllocVector_Remove(AllocVector* _vec, size_t _index)
- {
- if (_vec != NULL){
- Antler_Assert(_index >= 0);
- Antler_Assert(_index < _vec->count);
- size_t i = _index;
- for (i = _index; i < _vec->count - 1; i++) {
- _vec->items[i+1]->index = _vec->items[i+1]->index-1;
- _vec->items[i] = _vec->items[i + 1];
- }
- _vec->count--;
- if (_vec->count == _vec->capacity / 4)
- AllocVector_Resize(_vec, _vec->capacity / 2);
- }
- }
- void *Antler_Malloc_Impl(size_t sz, const char *file, int line)
- {
- if (vector == NULL)
- vector = MallocVector_Create(sizeof(Antler_Malloc_Info*), 5);
- Antler_Malloc_Info* info = malloc(sz + sizeof(*info));
- if (info == NULL) return info;
- info->file = file;
- info->line = line;
- info->size = sz;
- AllocVector_Push(vector, info);
- info->index = vector->count - 1;
- return info+1;
- }
- void *Antler_Calloc_Impl(size_t _nitems, size_t _sz, const char *_file, int _line)
- {
- size_t size = _nitems * _sz;
- void *ptr = Antler_Malloc_Impl(size, _file, _line);
- memset(ptr, 0, size);
- return ptr;
- }
- void Antler_Free_Impl(void *_ptr)
- {
- if (_ptr != NULL) {
- Antler_Malloc_Info *info = (Antler_Malloc_Info *)_ptr - 1;
- AllocVector_Remove(vector, info->index);
- free(info);
- if (vector->count == 0){
- free(vector->items);
- free(vector);
- vector = NULL;
- }
- }
- }
- void *Antler_Realloc_Impl(void *_ptr, size_t _sz, const char *_file, int _line)
- {
- if (_ptr == NULL) {
- return Antler_Malloc_Impl(_sz, _file, _line);
- }
- else if (_sz == 0) {
- Antler_Free_Impl(_ptr);
- return NULL;
- }
- else {
- Antler_Malloc_Info *info = (Antler_Malloc_Info *)_ptr - 1;
- if (_sz <= info->size)
- return _ptr;
- else {
- void *q = Antler_Malloc_Impl(_sz, _file, _line);
- if (q) {
- memcpy(q, _ptr, info->size);
- Antler_Free_Impl(_ptr);
- }
- return q;
- }
- }
- }
- static void Malloc_LeakPrint(const char *reason, const char *file, int line, size_t size, void *ptr)
- {
- #if (defined(_MSC_VER) && _MSC_VER < 1900) /* 1900=VS 2015 */ || defined(__MINGW32__)
- // 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 defined(_MSC_VER) && _MSC_VER < 1400 // before VS 2005
- printf("%-6s: %s (%4d): %8d bytes at %p\n", reason, file, line, (int)size, ptr);
- #else
- printf("%-6s: %s (%4d): %8lld bytes at %p\n", reason, file, line, (long long)size, ptr);
- #endif
- #else
- // Assume we have %zd on other targets.
- printf("%-6s: %s (%4d): %zd bytes at %p\n", reason, file, line, size, ptr);
- #endif
- }
- static void Malloc_Summary(const char *reason, int errcnt, size_t size)
- {
- #if (defined(_MSC_VER) && _MSC_VER < 1900) /* 1900=VS 2015 */ || defined(__MINGW32__)
- // 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 defined(_MSC_VER) && _MSC_VER < 1400 // before VS 2005
- printf("%-6s: %6d items totalling %8d bytes\n", reason, errcnt, (int)size);
- #else
- printf("%-6s: %6d items totalling %8lld bytes\n", reason, errcnt, (long long)size);
- #endif
- #else
- // Assume we have %zd on other targets.
- printf("%-6s: %6d items totalling %zd bytes\n", reason, errcnt, size);
- #endif
- }
- #endif
- size_t Antler_Malloc_NumLeaks(void)
- {
- #if defined(_DEBUG) || defined(DEBUG) || defined(_DEVELOPMENT)
- if (vector == NULL ) return 0;
- return vector->count;
- #else
- return 0;
- #endif
- }
- void Antler_Malloc_GetLeak(size_t _index, Antler_MallocLeak* _leak)
- {
- #if defined(_DEBUG) || defined(DEBUG) || defined(_DEVELOPMENT)
- if (vector == NULL) return;
- Antler_Assert(_index >= 0);
- Antler_Assert(_index < vector->count);
- Antler_Malloc_Info *info = vector->items[_index];
- _leak->file = info->file;
- _leak->line = info->line;
- _leak->size = info->size;
- _leak->address = info + 1;
- #endif
- }
- void Antler_Malloc_LeakDump()
- {
- #if defined(_DEBUG) || defined(DEBUG) || defined(_DEVELOPMENT)
- size_t i = 0;
- size_t size = 0;
- for (; i < Antler_Malloc_NumLeaks(); ++i){
- Antler_MallocLeak leak;
- Antler_Malloc_GetLeak(i, &leak);
- Malloc_LeakPrint("LEAKED", leak.file, leak.line, leak.size, leak.address);
- size += leak.size;
- }
- if(size) Malloc_Summary("LEAKED", Antler_Malloc_NumLeaks(), size);
- #endif
- }
Add Comment
Please, Sign In to add comment