/* * memoryleak.c * Copyright (C) Steffen Pohle 2009 * * main.c is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * main.c is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include #include #include #include "memoryleak.h" #include "system.h" #define MEMORY_DUMPINFO 1000 struct memoryleak_data memory[MEMORYLEAK_MAX]; int memory_used = 0; int memory_size = 0; int memory_blocknext = 0; struct memoryleak_data *ml_findfree (); struct memoryleak_data *ml_find (void *ptr); /************************************************************************/ struct memoryleak_data *ml_findfree () { int i; for (i = 0; i < MEMORYLEAK_MAX; i++) if (memory[i].ptr == NULL) return &memory[i]; return NULL; }; struct memoryleak_data *ml_find (void *ptr) { int i; for (i = 0; i < MEMORYLEAK_MAX; i++) if (memory[i].ptr == ptr) return &memory[i]; return NULL; }; void *ml_calloc(size_t nmemb, size_t size) { void *ptr; ptr = calloc(nmemb, size); d_printf ("memoryleak: function not yet fully implemented."); errorexit (-2); return ptr; }; void *ml_malloc(size_t size) { struct memoryleak_data *md = ml_findfree (); int i, j; void *buffer[ML_BT_SIZE]; char **strings; if (md == NULL) { d_printf ("memoryleak malloc MEMORYLEAK_MAX reached\n"); for (j = 0; j < MEMORYLEAK_MAX; j++) { d_printf ("memoryleak : (%6d) size:%d ptr:%p text:%s", j, memory[j].size, memory[j].ptr, memory[j].text); for (i = 1; i < memory[j].btcnt; i++) if (memory[j].ptr) // don't show ml_malloc call. d_printf (" frame:%3d %s", i, memory[j].btstr[i]); } errorexit (-1); } if (memory_size+size > MEMORYLEAK_MAXMEM) { d_printf ("ml_malloc: too much memory (%lu+%lu) %lu", memory_size, size, MEMORYLEAK_MAXMEM); errorexit (-1); } md->ptr = malloc (size); md->size = size; #if !defined(__MINGW32CE__) && !defined(_WIN32_WCE) && !defined(__MINGW32__) && !defined(ANDROID) md->btcnt = backtrace(buffer, ML_BT_SIZE); /* if someone finds out how this should really work please let me know? */ strings = (char **) backtrace_symbols(buffer, md->btcnt); if (strings == NULL) { d_printf ("backtrace_symbols: %s", strerror(errno)); exit(EXIT_FAILURE); } #else md->btcnt = 0; strings = NULL; #endif for (i = 0; (i < md->btcnt) && (i < ML_BT_SIZE); i++) { snprintf (md->btstr[i], ML_BT_TEXT, "%p:%s", buffer[i], strings[i]); } free(strings); md->text[0] = 0; memory_used ++; memory_size += size; return md->ptr; }; void ml_free(void *ptr) { struct memoryleak_data *md = ml_find (ptr); if (ptr == NULL) return; if (md == NULL) { d_printf ("memoryleak free NULL! allocated without unsing ml_ function?\n"); errorexit (-1); } memory_used--; memory_size -= md->size; free (md->ptr); md->ptr = NULL; md->text[0] = 0; md->size = 0; }; void *ml_realloc(void *ptr, size_t size) { struct memoryleak_data *md = ml_find (ptr); void *test = NULL; if (ptr == NULL) md = ml_findfree (); if (md == NULL) { d_printf ("memoryleak realloc NULL\n"); errorexit (-1); } memory_size = memory_size - md->size + size; if (memory_size > MEMORYLEAK_MAXMEM) { d_printf ("ml_realloc: too much memory %lld > %lld", memory_size, MEMORYLEAK_MAXMEM); errorexit (-1); } test = realloc (ptr, size); if (test == NULL && size > 0) { d_printf ("%s:%d (%s) test == NULL", __FILE__, __LINE__, __FUNCTION__); errorexit (-1); } md->ptr = test; md->size = size; return md->ptr; }; void ml_addinfo (void *ptr, char *text) { struct memoryleak_data *md = ml_find (ptr); if (md) { strncpy (md->text, text, ML_BT_TEXT); } }; void ml_get_stats (struct memoryleak_info *m) { m->blocks = memory_used; m->size = memory_size; // if (memory_used > memory_blocknext) { // ml_debug (); // while (memory_used > memory_blocknext) memory_blocknext += MEMORY_DUMPINFO; // } }; void ml_init () { int i; for (i = 0; i < MEMORYLEAK_MAX; i++) { memory[i].size = 0; memory[i].ptr = NULL; } }; void ml_debug () { int i, j; void *ptr1, *ptr2; ptr1 = (void*)&i; ptr2 = ptr1+1; d_printf ("*** memoryleak debug: %p, %p", ptr1, ptr2); d_printf ("size void:%d char:%d", sizeof (void), sizeof (char)); for (j = 0; j < MEMORYLEAK_MAX; j++) if (memory[j].ptr) { d_printf (" memory(%6d) size:%d ptr:%p text:%s", j, memory[j].size, memory[j].ptr, memory[j].text); for (i = 1; i < memory[j].btcnt; i++) if (memory[j].ptr) // don't show ml_malloc call. d_printf (" frame:%3d %s", i, memory[j].btstr[i]); } };