31 #include <sys/types.h>
38 #include "../../source/blender/blenlib/BLI_strict_flags.h"
64 #ifdef DEBUG_BACKTRACE
65 # define BACKTRACE_SIZE 100
68 #ifdef DEBUG_MEMCOUNTER
70 # define DEBUG_MEMCOUNTER_ERROR_VAL 0
71 static int _mallocn_count = 0;
74 static void memcount_raise(
const char *name)
76 fprintf(stderr,
"%s: memcount-leak, %d\n", name, _mallocn_count);
104 #ifdef DEBUG_MEMCOUNTER
108 #ifdef DEBUG_MEMDUPLINAME
109 int need_free_name, pad;
112 #ifdef DEBUG_BACKTRACE
113 void *backtrace[BACKTRACE_SIZE];
120 #ifdef DEBUG_BACKTRACE
121 # if defined(__linux__) || defined(__APPLE__)
122 # include <execinfo.h>
147 #ifdef __BIG_ENDIAN__
148 # define MAKE_ID(a, b, c, d) ((int)(a) << 24 | (int)(b) << 16 | (c) << 8 | (d))
150 # define MAKE_ID(a, b, c, d) ((int)(d) << 24 | (int)(c) << 16 | (b) << 8 | (a))
153 #define MEMTAG1 MAKE_ID('M', 'E', 'M', 'O')
154 #define MEMTAG2 MAKE_ID('R', 'Y', 'B', 'L')
155 #define MEMTAG3 MAKE_ID('O', 'C', 'K', '!')
156 #define MEMFREE MAKE_ID('F', 'R', 'E', 'E')
158 #define MEMNEXT(x) ((MemHead *)(((char *)x) - offsetof(MemHead, next)))
190 __attribute__((
format(printf, 1, 2)))
199 vsnprintf(buf,
sizeof(buf),
str, ap);
201 buf[
sizeof(buf) - 1] =
'\0';
225 const char *err_val =
NULL;
233 return (err_val ==
NULL);
266 #ifndef DEBUG_MEMDUPLINAME
280 char *name = malloc(strlen(memh->
name) + 24);
283 sprintf(name,
"%s %s",
"dupli_alloc", memh->
name);
287 sprintf(name,
"%s %s",
"dupli_alloc", memh->
name);
297 nmemh->need_free_name = 1;
301 memcpy(newp, vmemh, memh->
len);
323 if (len < memh->
len) {
325 memcpy(newp, vmemh,
len);
329 memcpy(newp, vmemh, memh->
len);
358 if (len < memh->
len) {
360 memcpy(newp, vmemh,
len);
363 memcpy(newp, vmemh, memh->
len);
368 memset(((
char *)newp) + memh->
len, 0,
len - memh->
len);
382 #ifdef DEBUG_BACKTRACE
383 # if defined(__linux__) || defined(__APPLE__)
384 static void make_memhead_backtrace(
MemHead *memh)
386 memh->backtrace_size = backtrace(memh->backtrace, BACKTRACE_SIZE);
389 static void print_memhead_backtrace(
MemHead *memh)
394 strings = backtrace_symbols(memh->backtrace, memh->backtrace_size);
395 for (i = 0; i < memh->backtrace_size; i++) {
402 static void make_memhead_backtrace(
MemHead *memh)
407 static void print_memhead_backtrace(
MemHead *memh)
426 #ifdef DEBUG_MEMDUPLINAME
427 memh->need_free_name = 0;
430 #ifdef DEBUG_BACKTRACE
431 make_memhead_backtrace(memh);
460 memset(memh + 1, 255,
len);
463 #ifdef DEBUG_MEMCOUNTER
464 if (_mallocn_count == DEBUG_MEMCOUNTER_ERROR_VAL)
465 memcount_raise(__func__);
466 memh->_count = _mallocn_count++;
482 "Malloc array aborted due to integer overflow: "
516 assert(alignment < 1024);
528 memh = (
MemHead *)((
char *)memh + extra_padding);
533 memset(memh + 1, 255,
len);
536 #ifdef DEBUG_MEMCOUNTER
537 if (_mallocn_count == DEBUG_MEMCOUNTER_ERROR_VAL)
538 memcount_raise(__func__);
539 memh->_count = _mallocn_count++;
560 #ifdef DEBUG_MEMCOUNTER
561 if (_mallocn_count == DEBUG_MEMCOUNTER_ERROR_VAL)
562 memcount_raise(__func__);
563 memh->_count = _mallocn_count++;
579 "Calloc array aborted due to integer overflow: "
604 return strcmp(pb1->
name, pb2->
name);
612 if (pb1->
len < pb2->
len) {
615 if (pb1->
len == pb2->
len) {
626 unsigned int totpb,
a, b;
627 size_t mem_in_use_slop = 0;
637 print_error(
"malloc returned null while generating stats");
653 while (membl && pb) {
661 #ifdef USE_MALLOC_USABLE_SIZE
663 mem_in_use_slop += (
sizeof(
MemHead) +
sizeof(
MemTail) + malloc_usable_size((
void *)membl)) -
681 for (
a = 0, b = 0;
a < totpb;
a++) {
685 if (strcmp(printblock[
a].name, printblock[b].name) == 0) {
686 printblock[b].
len += printblock[
a].
len;
687 printblock[b].
items++;
701 printf(
"\ntotal memory len: %.3f MB\n", (
double)
mem_in_use / (
double)(1024 * 1024));
702 printf(
"peak memory len: %.3f MB\n", (
double)
peak_mem / (
double)(1024 * 1024));
703 printf(
"slop memory len: %.3f MB\n", (
double)mem_in_use_slop / (
double)(1024 * 1024));
704 printf(
" ITEMS TOTAL-MiB AVERAGE-KiB TYPE\n");
705 for (
a = 0, pb = printblock;
a < totpb;
a++, pb++) {
706 printf(
"%6d (%8.3f %8.3f) %s\n",
708 (
double)pb->
len / (
double)(1024 * 1024),
709 (
double)pb->
len / 1024.0 / (
double)pb->
items,
713 if (printblock !=
NULL) {
719 #ifdef HAVE_MALLOC_STATS
720 printf(
"System Statistics:\n");
728 "for mb_item in membase:\n"
729 " mb_item_user_size = mb_userinfo.setdefault(mb_item['name'], [0,0])\n"
730 " mb_item_user_size[0] += 1 # Add a user\n"
731 " mb_item_user_size[1] += mb_item['len'] # Increment the size\n"
732 " totmem += mb_item['len']\n"
733 "print('(membase) items:', len(membase), '| unique-names:',\n"
734 " len(mb_userinfo), '| total-mem:', totmem)\n"
735 "mb_userinfo_sort = list(mb_userinfo.items())\n"
736 "for sort_name, sort_func in (('size', lambda a: -a[1][1]),\n"
737 " ('users', lambda a: -a[1][0]),\n"
738 " ('name', lambda a: a[0])):\n"
739 " print('\\nSorting by:', sort_name)\n"
740 " mb_userinfo_sort.sort(key = sort_func)\n"
741 " for item in mb_userinfo_sort:\n"
742 " print('name:%%s, users:%%i, len:%%i' %%\n"
743 " (item[0], item[1][0], item[1][1]))\n";
766 "'pointer':'%p'},\n",
769 (
void *)(membl + 1));
772 #ifdef DEBUG_MEMCOUNTER
782 (
void *)(membl + 1));
784 #ifdef DEBUG_BACKTRACE
785 print_memhead_backtrace(membl);
828 short MEM_guarded_testN(
void *vmemh)
839 if (vmemh == membl + 1) {
852 print_error(
"Memoryblock %p: pointer not in memlist\n", vmemh);
880 MemorY_ErroR(
"free",
"attempt to free illegal pointer");
886 MemorY_ErroR(
"free",
"attempt to free illegal pointer");
916 if (name != memh->name) {
950 if (listbase ==
NULL)
957 if (listbase->
last) {
961 listbase->
first = link;
963 listbase->
last = link;
975 if (listbase ==
NULL)
986 if (listbase->
last == link) {
989 if (listbase->
first == link) {
1011 #ifdef DEBUG_MEMDUPLINAME
1012 if (memh->need_free_name)
1017 memset(memh + 1, 255, memh->
len);
1031 #ifdef WITH_ASSERT_ABORT
1038 MemHead *forw, *back, *forwok, *backok;
1078 return (
"MORE THAN 1 MEMORYBLOCK CORRUPT");
1081 if (forw ==
NULL && back ==
NULL) {
1134 name =
"No name found";
1162 return (
"Additional error in header");
1199 unsigned int _totblock;
1217 return "MEM_guarded_name_ptr(NULL)";
void BLI_kdtree_nd_() free(KDTree *tree)
Read Guarded memory(de)allocation.
Provides wrapper around system-specific atomic primitives, and some extensions (faked-atomic operatio...
ATOMIC_INLINE size_t atomic_add_and_fetch_z(size_t *p, size_t x)
ATOMIC_INLINE size_t atomic_sub_and_fetch_z(size_t *p, size_t x)
ATOMIC_INLINE unsigned int atomic_add_and_fetch_u(unsigned int *p, unsigned int x)
ATOMIC_INLINE unsigned int atomic_sub_and_fetch_u(unsigned int *p, unsigned int x)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
bool leak_detector_has_run
char free_after_leak_detection_message[]
void aligned_free(void *ptr)
void * aligned_malloc(size_t size, size_t alignment)
static pthread_mutex_t thread_lock
static void MEM_guarded_printmemlist_internal(int pydict)
static void rem_memblock(MemHead *memh)
static const char mem_printmemlist_pydict_script[]
size_t MEM_guarded_allocN_len(const void *vmemh)
const char * MEM_guarded_name_ptr(void *vmemh)
unsigned int MEM_guarded_get_memory_blocks_in_use(void)
static volatile struct localListBase * membase
static int compare_len(const void *p1, const void *p2)
static int compare_name(const void *p1, const void *p2)
static volatile struct localListBase _membase
void * MEM_guarded_callocN(size_t len, const char *str)
static void remlink(volatile localListBase *listbase, void *vlink)
struct localListBase localListBase
void * MEM_guarded_dupallocN(const void *vmemh)
void * MEM_guarded_calloc_arrayN(size_t len, size_t size, const char *str)
void MEM_guarded_set_error_callback(void(*func)(const char *))
void MEM_guarded_printmemlist(void)
void MEM_guarded_printmemlist_pydict(void)
static bool malloc_debug_memset
struct MemPrintBlock MemPrintBlock
void MEM_guarded_callbackmemlist(void(*func)(void *))
static unsigned int totblock
static void(* error_callback)(const char *)
static void MemorY_ErroR(const char *block, const char *error)
bool MEM_guarded_consistency_check(void)
static void mem_unlock_thread(void)
static void mem_lock_thread(void)
void MEM_guarded_set_memory_debug(void)
static void print_error(const char *str,...)
void MEM_guarded_printmemlist_stats(void)
static void make_memhead_header(MemHead *memh, size_t len, const char *str)
size_t MEM_guarded_get_peak_memory(void)
static void addtail(volatile localListBase *listbase, void *vlink)
void * MEM_guarded_malloc_arrayN(size_t len, size_t size, const char *str)
void * MEM_guarded_mallocN(size_t len, const char *str)
void * MEM_guarded_mallocN_aligned(size_t len, size_t alignment, const char *str)
void * MEM_guarded_reallocN_id(void *vmemh, size_t len, const char *str)
void * MEM_guarded_recallocN_id(void *vmemh, size_t len, const char *str)
void MEM_guarded_reset_peak_memory(void)
struct localLink localLink
size_t MEM_guarded_get_memory_in_use(void)
static const char * check_memlist(MemHead *memh)
void MEM_guarded_freeN(void *vmemh)
MEM_INLINE bool MEM_size_safe_multiply(size_t a, size_t b, size_t *result)
#define MEMHEAD_REAL_PTR(memh)
#define MEMHEAD_ALIGN_PADDING(alignment)
#define SIZET_ALIGN_4(len)
static void error(const char *str)
_W64 unsigned int uintptr_t