15 #include <sys/types.h>
22 #include "../../source/blender/blenlib/BLI_strict_flags.h"
48 #ifdef DEBUG_BACKTRACE
49 # define BACKTRACE_SIZE 100
52 #ifdef DEBUG_MEMCOUNTER
54 # define DEBUG_MEMCOUNTER_ERROR_VAL 0
55 static int _mallocn_count = 0;
58 static void memcount_raise(
const char *name)
60 fprintf(stderr,
"%s: memcount-leak, %d\n", name, _mallocn_count);
87 #ifdef DEBUG_MEMCOUNTER
91 #ifdef DEBUG_MEMDUPLINAME
92 int need_free_name,
pad;
95 #ifdef DEBUG_BACKTRACE
96 void *backtrace[BACKTRACE_SIZE];
103 #ifdef DEBUG_BACKTRACE
104 # if defined(__linux__) || defined(__APPLE__)
105 # include <execinfo.h>
130 #ifdef __BIG_ENDIAN__
131 # define MAKE_ID(a, b, c, d) ((int)(a) << 24 | (int)(b) << 16 | (c) << 8 | (d))
133 # define MAKE_ID(a, b, c, d) ((int)(d) << 24 | (int)(c) << 16 | (b) << 8 | (a))
136 #define MEMTAG1 MAKE_ID('M', 'E', 'M', 'O')
137 #define MEMTAG2 MAKE_ID('R', 'Y', 'B', 'L')
138 #define MEMTAG3 MAKE_ID('O', 'C', 'K', '!')
139 #define MEMFREE MAKE_ID('F', 'R', 'E', 'E')
141 #define MEMNEXT(x) ((MemHead *)(((char *)x) - offsetof(MemHead, next)))
182 vsnprintf(buf,
sizeof(buf),
str, ap);
184 buf[
sizeof(buf) - 1] =
'\0';
208 const char *err_val =
NULL;
216 return (err_val ==
NULL);
249 #ifndef DEBUG_MEMDUPLINAME
263 char *name = malloc(strlen(memh->
name) + 24);
266 sprintf(name,
"%s %s",
"dupli_alloc", memh->
name);
270 sprintf(name,
"%s %s",
"dupli_alloc", memh->
name);
280 nmemh->need_free_name = 1;
284 memcpy(newp, vmemh, memh->
len);
306 if (len < memh->
len) {
308 memcpy(newp, vmemh,
len);
312 memcpy(newp, vmemh, memh->
len);
341 if (len < memh->
len) {
343 memcpy(newp, vmemh,
len);
346 memcpy(newp, vmemh, memh->
len);
351 memset(((
char *)newp) + memh->
len, 0,
len - memh->
len);
365 #ifdef DEBUG_BACKTRACE
366 # if defined(__linux__) || defined(__APPLE__)
367 static void make_memhead_backtrace(
MemHead *memh)
369 memh->backtrace_size = backtrace(memh->backtrace, BACKTRACE_SIZE);
372 static void print_memhead_backtrace(
MemHead *memh)
377 strings = backtrace_symbols(memh->backtrace, memh->backtrace_size);
378 for (i = 0; i < memh->backtrace_size; i++) {
385 static void make_memhead_backtrace(
MemHead *memh)
390 static void print_memhead_backtrace(
MemHead *memh)
409 #ifdef DEBUG_MEMDUPLINAME
410 memh->need_free_name = 0;
413 #ifdef DEBUG_BACKTRACE
414 make_memhead_backtrace(memh);
443 memset(memh + 1, 255,
len);
446 #ifdef DEBUG_MEMCOUNTER
447 if (_mallocn_count == DEBUG_MEMCOUNTER_ERROR_VAL)
448 memcount_raise(__func__);
449 memh->_count = _mallocn_count++;
465 "Malloc array aborted due to integer overflow: "
499 assert(alignment < 1024);
511 memh = (
MemHead *)((
char *)memh + extra_padding);
516 memset(memh + 1, 255,
len);
519 #ifdef DEBUG_MEMCOUNTER
520 if (_mallocn_count == DEBUG_MEMCOUNTER_ERROR_VAL)
521 memcount_raise(__func__);
522 memh->_count = _mallocn_count++;
543 #ifdef DEBUG_MEMCOUNTER
544 if (_mallocn_count == DEBUG_MEMCOUNTER_ERROR_VAL)
545 memcount_raise(__func__);
546 memh->_count = _mallocn_count++;
562 "Calloc array aborted due to integer overflow: "
587 return strcmp(pb1->
name, pb2->
name);
595 if (pb1->
len < pb2->
len) {
598 if (pb1->
len == pb2->
len) {
609 unsigned int totpb,
a,
b;
610 size_t mem_in_use_slop = 0;
620 print_error(
"malloc returned null while generating stats");
636 while (membl && pb) {
644 #ifdef USE_MALLOC_USABLE_SIZE
646 mem_in_use_slop += (
sizeof(
MemHead) +
sizeof(
MemTail) + malloc_usable_size((
void *)membl)) -
664 for (
a = 0,
b = 0;
a < totpb;
a++) {
668 if (strcmp(printblock[
a].name, printblock[
b].name) == 0) {
669 printblock[
b].
len += printblock[
a].
len;
684 printf(
"\ntotal memory len: %.3f MB\n", (
double)
mem_in_use / (
double)(1024 * 1024));
685 printf(
"peak memory len: %.3f MB\n", (
double)
peak_mem / (
double)(1024 * 1024));
686 printf(
"slop memory len: %.3f MB\n", (
double)mem_in_use_slop / (
double)(1024 * 1024));
687 printf(
" ITEMS TOTAL-MiB AVERAGE-KiB TYPE\n");
688 for (
a = 0, pb = printblock;
a < totpb;
a++, pb++) {
689 printf(
"%6d (%8.3f %8.3f) %s\n",
691 (
double)pb->
len / (
double)(1024 * 1024),
692 (
double)pb->
len / 1024.0 / (
double)pb->
items,
696 if (printblock !=
NULL) {
702 #ifdef HAVE_MALLOC_STATS
703 printf(
"System Statistics:\n");
711 "for mb_item in membase:\n"
712 " mb_item_user_size = mb_userinfo.setdefault(mb_item['name'], [0,0])\n"
713 " mb_item_user_size[0] += 1 # Add a user\n"
714 " mb_item_user_size[1] += mb_item['len'] # Increment the size\n"
715 " totmem += mb_item['len']\n"
716 "print('(membase) items:', len(membase), '| unique-names:',\n"
717 " len(mb_userinfo), '| total-mem:', totmem)\n"
718 "mb_userinfo_sort = list(mb_userinfo.items())\n"
719 "for sort_name, sort_func in (('size', lambda a: -a[1][1]),\n"
720 " ('users', lambda a: -a[1][0]),\n"
721 " ('name', lambda a: a[0])):\n"
722 " print('\\nSorting by:', sort_name)\n"
723 " mb_userinfo_sort.sort(key = sort_func)\n"
724 " for item in mb_userinfo_sort:\n"
725 " print('name:%%s, users:%%i, len:%%i' %%\n"
726 " (item[0], item[1][0], item[1][1]))\n";
749 "'pointer':'%p'},\n",
752 (
void *)(membl + 1));
755 #ifdef DEBUG_MEMCOUNTER
765 (
void *)(membl + 1));
767 #ifdef DEBUG_BACKTRACE
768 print_memhead_backtrace(membl);
811 short MEM_guarded_testN(
void *vmemh)
822 if (vmemh == membl + 1) {
835 print_error(
"Memoryblock %p: pointer not in memlist\n", vmemh);
863 MemorY_ErroR(
"free",
"attempt to free illegal pointer");
869 MemorY_ErroR(
"free",
"attempt to free illegal pointer");
899 if (name != memh->name) {
933 if (listbase ==
NULL)
940 if (listbase->
last) {
944 listbase->
first = link;
946 listbase->
last = link;
958 if (listbase ==
NULL)
969 if (listbase->
last == link) {
972 if (listbase->
first == link) {
994 #ifdef DEBUG_MEMDUPLINAME
995 if (memh->need_free_name)
1000 memset(memh + 1, 255, memh->
len);
1014 #ifdef WITH_ASSERT_ABORT
1021 MemHead *forw, *back, *forwok, *backok;
1061 return (
"MORE THAN 1 MEMORYBLOCK CORRUPT");
1064 if (forw ==
NULL && back ==
NULL) {
1117 name =
"No name found";
1145 return (
"Additional error in header");
1182 unsigned int _totblock;
1200 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)
struct AtomicSpinLock __attribute__((aligned(32))) AtomicSpinLock
int pad[32 - sizeof(int)]
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
SyclQueue void void size_t num_bytes void
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)
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
_W64 unsigned int uintptr_t