You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
214 lines
4.9 KiB
214 lines
4.9 KiB
/*
|
|
* memoryleak.c
|
|
* Copyright (C) Steffen Pohle 2009 <steffen@gulpe.de>
|
|
*
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#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]);
|
|
}
|
|
};
|