/* Copyright (c) 2018 Muresan Vlad Mihail Contact Info muresanvladmihail@gmail.com, murii@tilde.team Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. Shall you use this software in a product, an acknowledgment and the contact info(if there is any) of the author(s) must be placed in the product documentation. 2. This notice may not be removed or altered from any source distribution. 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include "vector.h" #include "mlc.h" typedef struct { const char* file; /* file in which the allocation happened */ size_t line; /* line at which the allocation happened */ size_t size; /* the size of allocated object */ char free; /* 1-> free, 0-> not free yet */ void* ptr; /* the actual object which is allocated */ } alloc_struct; static vec_t* elements_v; /* holds all allocated structures */ void mlc_init() { elements_v = vec_init(sizeof(void*)); } void mlc_destroy() { vec_destroy(elements_v); } static void add_structure(void* ptr, size_t obj_size, const char* file, unsigned line) { alloc_struct* ns = malloc(sizeof(alloc_struct)); if (!ns) { #ifdef MLC_CHECK_FOR_ERRORS fprintf(stderr, "Couldn't allocate mlc structure: %s, line %u\n", file, line); #endif return; } ns->file = file; ns->line = line; ns->size = obj_size; ns->ptr = ptr; ns->free = 0; vec_append(elements_v, ns); } static long has_structure(void* ptr) { size_t i = 0; while (i < vec_size(elements_v)) { alloc_struct *str = (alloc_struct*)vec_get(elements_v, i); if (str->ptr == ptr) return i; i++; } return -1; } void* _mlc_malloc(size_t size, const char* file, unsigned line) { void* ptr = malloc(size); if (!ptr) { #ifdef MLC_CHECK_FOR_ERRORS fprintf(stderr, "Couldn't allocate: %s, line %u\n", file, line); #endif return NULL; } #ifdef MLC_ACT_NORMAL return ptr; #endif add_structure(ptr, size, file, line); return ptr; } void* _mlc_calloc(size_t nitems, size_t size, const char* file, unsigned line) { void* ptr = calloc(nitems, size); if (!ptr) { #ifdef MLC_CHECK_FOR_ERRORS fprintf(stderr, "Couldn't allocate: %s, line %u\n", file, line); #endif return NULL; } #ifdef MLC_ACT_NORMAL return ptr; #endif add_structure(ptr, size, file, line); return ptr; } void* _mlc_realloc(void* ptr, size_t size, const char* file, unsigned line) { #ifdef MLC_ACT_NORMAL void* _ptr = realloc(ptr, size); if (!_ptr) { #ifdef MLC_CHECK_FOR_ERRORS fprintf(stderr, "Couldn't reallocate: %s, line %u\n", file, line); #endif return NULL; } return _ptr; #endif void* _ptr = realloc(ptr, size); alloc_struct* as = NULL; size_t index = 0; if (!_ptr) { #ifdef MLC_CHECK_FOR_ERRORS fprintf(stderr, "Couldn't reallocate: %s, line %u\n", file, line); #endif return NULL; } index = has_structure(ptr); as = (alloc_struct*)vec_get(elements_v, index); if (!as) { #ifdef MLC_CHECK_FOR_WARNINGS fprintf(stdout, "Reallocating is happening on a NULL ptr %s %u\n", file, line); #endif add_structure(_ptr, size, file, line); } else { as->ptr = _ptr; as->size = size; } return _ptr; } void _mlc_free(void* ptr, const char* file, unsigned line) { #ifdef MLC_ACT_NORMAL free(ptr); #endif alloc_struct* as = NULL; size_t index = 0; if (ptr == NULL) { #ifdef MLC_CHECK_FOR_WARNINGS fprintf(stderr, "Couldn't free object: %s, line %u %s \n", file, line, " because it's NULL"); #endif return; } index = has_structure(ptr); if (index < 0) return; as = (alloc_struct*)vec_get(elements_v, index); if (!as) { #ifdef MLC_CHECK_FOR_WARNINGS fprintf(stderr, "Invalid free: %s, line %u\n", file, line); #endif return; } else { as->free = 1; } free(ptr); ptr = NULL; } size_t _mlc_size(void* ptr, const char* file, unsigned line) { alloc_struct* _ptr = (alloc_struct*)vec_get(elements_v, has_structure(ptr)); if (!ptr) { #ifdef MLC_CHECK_FOR_WARNINGS fprintf(stderr, "Bad pointer: %s, line %u\n", file, line); #endif return -1; } return _ptr->size; } size_t mlc_usage() { #ifdef MLC_ACT_NORMAL return 0; #endif size_t usage = 0; size_t i = 0; while (i < vec_size(elements_v)) { alloc_struct* ptr = ((alloc_struct*)vec_get(elements_v, i)); if (ptr->free == 0) usage += ptr->size; i++; } return usage; } void mlc_dump(FILE* file) { #ifdef MLC_ACT_NORMAL return; #endif alloc_struct* curr = NULL; size_t i = 0; size_t size = vec_size(elements_v); if (!file) file = stdout; if (size == 0) fprintf(file, "MLC: no memory leaks! \n"); while (i < size) { curr = vec_get(elements_v, i); if (curr->free == 0) fprintf(file, "MLC: Unfreed: %p %s, line %zu\n", curr->ptr, curr->file, curr->line); i++; } }