forked from bartvdbraak/blender
Backtrace for unfreed memory blocks
Added an option to show backtrace from where non-freed datablock was allocated from. To enable this feature, simply enable DEBUG_BACKTRACE in mallocn.c file and all unfreed datablocks will be followed up by a backtrace. Currently works on linux and osx only, windows support is on TODO. This feature is for sure disabled by default, so does not affect any builds which don't explicitly define DEBUG_BACKTRACE.
This commit is contained in:
parent
7586580241
commit
1be2936298
@ -87,6 +87,17 @@
|
||||
*/
|
||||
//#define DEBUG_THREADS
|
||||
|
||||
/* Only for debugging:
|
||||
* Defining DEBUG_BACKTRACE will store a backtrace from where
|
||||
* memory block was allocated and print this trace for all
|
||||
* unfreed blocks.
|
||||
*/
|
||||
#define DEBUG_BACKTRACE
|
||||
|
||||
#ifdef DEBUG_BACKTRACE
|
||||
# define BACKTRACE_SIZE 100
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_MEMCOUNTER
|
||||
/* set this to the value that isn't being freed */
|
||||
# define DEBUG_MEMCOUNTER_ERROR_VAL 0
|
||||
@ -127,6 +138,11 @@ typedef struct MemHead {
|
||||
#ifdef DEBUG_MEMDUPLINAME
|
||||
int need_free_name, pad;
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_BACKTRACE
|
||||
void *backtrace[BACKTRACE_SIZE];
|
||||
int backtrace_size;
|
||||
#endif
|
||||
} MemHead;
|
||||
|
||||
/* for openmp threading asserts, saves time troubleshooting
|
||||
@ -147,6 +163,15 @@ typedef struct MemHead {
|
||||
static pthread_t mainid;
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_BACKTRACE
|
||||
# if defined(__linux__) || defined(__APPLE__)
|
||||
# include <execinfo.h>
|
||||
// Windows is not supported yet.
|
||||
//# elif defined(_MSV_VER)
|
||||
//# include <DbgHelp.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
typedef struct MemTail {
|
||||
int tag3, pad;
|
||||
} MemTail;
|
||||
@ -409,6 +434,38 @@ void *MEM_recallocN(void *vmemh, size_t len)
|
||||
return newp;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_BACKTRACE
|
||||
# if defined(__linux__) || defined(__APPLE__)
|
||||
static void make_memhead_backtrace(MemHead *memh)
|
||||
{
|
||||
memh->backtrace_size = backtrace(memh->backtrace, BACKTRACE_SIZE);
|
||||
}
|
||||
|
||||
static void print_memhead_backtrace(MemHead *memh)
|
||||
{
|
||||
char **strings;
|
||||
int i;
|
||||
|
||||
strings = backtrace_symbols(memh->backtrace, memh->backtrace_size);
|
||||
for (i = 0; i < memh->backtrace_size; i++) {
|
||||
print_error(" %s\n", strings[i]);
|
||||
}
|
||||
|
||||
free(strings);
|
||||
}
|
||||
# else
|
||||
static void make_memhead_backtrace(MemHead *memh)
|
||||
{
|
||||
(void) memh; /* Ignored. */
|
||||
}
|
||||
|
||||
static void print_memhead_backtrace(MemHead *memh)
|
||||
{
|
||||
(void) memh; /* Ignored. */
|
||||
}
|
||||
# endif /* defined(__linux__) || defined(__APPLE__) */
|
||||
#endif /* DEBUG_BACKTRACE */
|
||||
|
||||
static void make_memhead_header(MemHead *memh, size_t len, const char *str)
|
||||
{
|
||||
MemTail *memt;
|
||||
@ -424,6 +481,10 @@ static void make_memhead_header(MemHead *memh, size_t len, const char *str)
|
||||
memh->need_free_name = 0;
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_BACKTRACE
|
||||
make_memhead_backtrace(memh);
|
||||
#endif
|
||||
|
||||
memt = (MemTail *)(((char *) memh) + sizeof(MemHead) + len);
|
||||
memt->tag3 = MEMTAG3;
|
||||
|
||||
@ -673,6 +734,9 @@ static void MEM_printmemlist_internal(int pydict)
|
||||
#else
|
||||
print_error("%s len: " SIZET_FORMAT " %p\n",
|
||||
membl->name, SIZET_ARG(membl->len), membl + 1);
|
||||
#endif
|
||||
#ifdef DEBUG_BACKTRACE
|
||||
print_memhead_backtrace(membl);
|
||||
#endif
|
||||
}
|
||||
if (membl->next)
|
||||
|
Loading…
Reference in New Issue
Block a user