diff options
author | klto <klto@bb4c1ae6-6eb5-4d93-a66e-2307d6765a9c> | 2010-10-28 07:33:28 +0000 |
---|---|---|
committer | klto <klto@bb4c1ae6-6eb5-4d93-a66e-2307d6765a9c> | 2010-10-28 07:33:28 +0000 |
commit | 2f7a7f07846aa498b4b79a83bbe425d7aba73f03 (patch) | |
tree | 18c49cd2e8f09c6df38ceab570f72dd52dd51773 /memdebug | |
parent | b29885c60c5b8f1b204e78902df728121b5e7cf2 (diff) | |
parent | 098c2b10024f57666e381889438e5250ef882a44 (diff) |
Merge branch 'master' into local-svn
git-svn-id: https://parma.zhaw.ch/svn/csnippets@2 bb4c1ae6-6eb5-4d93-a66e-2307d6765a9c
Diffstat (limited to 'memdebug')
-rw-r--r-- | memdebug/memdebug.c | 133 | ||||
-rw-r--r-- | memdebug/memdebug.h | 42 |
2 files changed, 175 insertions, 0 deletions
diff --git a/memdebug/memdebug.c b/memdebug/memdebug.c new file mode 100644 index 0000000..84a2c86 --- /dev/null +++ b/memdebug/memdebug.c @@ -0,0 +1,133 @@ +/* + * memdebug - A simple malloc/free debugger + * + * This can essentially be useful on embedded systems platforms where tools such + * as valgrind are not available. + * + * Copyright (c) 2010, Tobias Klauser <tklauser@distanz.ch> + */ + +#include <stdio.h> +#include <stdlib.h> + +/* define/undef to enable tracing of errors */ +#define MEMDEBUG_TRACE + +#include "memdebug.h" + +static struct memdebug_heap_item *heap_head = NULL; +static struct memdebug_heap_item *heap_tail = NULL; + +void memdebug_start(void) +{ + /* Empty for now */ +} + +void memdebug_cleanup(void) +{ + struct memdebug_heap_item *hi; + + for (hi = heap_head; hi; hi = hi->next) { + if (hi->addr) + free(hi->addr); + free(hi); + } + + heap_head = NULL; + heap_tail = NULL; +} + +void *__memdebug_malloc(size_t size, const char *func, + const char *file, const unsigned int line) +{ + void *ret; + struct memdebug_heap_item *hi = malloc(sizeof(struct memdebug_heap_item)); + + if (!hi) + goto out_err; + + ret = malloc(size); + if (!ret) { + free(hi); + goto out_err; + } + + hi->next = NULL; + hi->addr = ret; + hi->size = size; + hi->func = func; + hi->file = file; + hi->line = line; + hi->freed_func = NULL; + hi->freed_file = NULL; + hi->line = 0; + + if (!heap_head) + heap_head = hi; + if (heap_tail) + heap_tail->next = hi; + heap_tail = hi; + + return ret; + +out_err: + memdebug_trace("malloc failed (%s:%d:%s)", file, line, func); + return NULL; +} + +void __memdebug_free(void *ptr, const char *func, + const char *file, const unsigned int line) +{ + struct memdebug_heap_item *hi, *prev; + + if (!ptr) { + memdebug_trace("trying to free NULL pointer (%s:%d:%s)", file, line, func); + return; + } + + for (hi = heap_head, prev = NULL; hi; prev = hi, hi = hi->next) + if (hi->addr == ptr) + break; + + if (!hi) { + memdebug_trace("no memory allocated at %p (%s:%d:%s)", ptr, file, line, func); + return; + } + + if (hi->freed_func) { + memdebug_trace("double free at %p (%s:%d:%s)\nalready freed by %s:%d:%s", + ptr, file, line, func, hi->freed_file, hi->freed_line, hi->freed_func); + return; + } + + hi->freed_func = func; + hi->freed_file = file; + hi->freed_line = line; + + /* Free the memory but keep the memdebug information */ + free(hi->addr); + hi->addr = NULL; +} + +void memdebug_report(int report_all) +{ + struct memdebug_heap_item *hi; + size_t total_size = 0; + size_t still_allocated = 0; + + fprintf(stderr, "\n\n*** Reporting allocated/freed memory ***\n"); + for (hi = heap_head; hi; hi = hi->next) { + if (hi->addr) { + fprintf(stderr, " IN USE %zu bytes at %p (%s:%d:%s)\n", + hi->size, hi->addr, hi->file, hi->line, hi->func); + still_allocated += hi->size; + } else if (report_all) { + fprintf(stderr, " FREE %zu bytes at %p (%s:%d:%s)\n", + hi->size, hi->addr, hi->file, hi->line, hi->func); + } + total_size += hi->size; + } + fprintf(stderr, "Total size: %zu bytes, %zu bytes still allocated\n\n", + total_size, still_allocated); + fflush(stderr); +} diff --git a/memdebug/memdebug.h b/memdebug/memdebug.h new file mode 100644 index 0000000..7a816c0 --- /dev/null +++ b/memdebug/memdebug.h @@ -0,0 +1,42 @@ +#ifndef _MEMDEBUG_H_ +#define _MEMDEBUG_H_ + +#include <stdlib.h> + +#ifdef MEMDEBUG_TRACE +# define memdebug_trace(fmt, args...) \ + ({ \ + fprintf(stderr, "*** " fmt " ***\n", ##args); \ + fflush(stderr); \ + }) +#else +# define memdebug_trace(fmt, args...) +#endif + +struct memdebug_heap_item { + struct memdebug_heap_item *next; + + void *addr; + size_t size; + + const char *func; + const char *file; + unsigned int line; + + const char *freed_func; + const char *freed_file; + unsigned int freed_line; +}; + +#define memdebug_malloc(size) \ + __memdebug_malloc(size, __func__, __FILE__, __LINE__) +#define memdebug_free(ptr) \ + __memdebug_free(ptr, __func__, __FILE__, __LINE__) + +void *__memdebug_malloc(size_t size, const char *func, + const char *file, const unsigned int line); +void __memdebug_free(void *ptr, const char *func, + const char *file, const unsigned int line); +void memdebug_report(int report_all); + +#endif /* _MEMDEBUG_H_ */ |