40#ifndef __MEM_GUARDEDALLOC_H__
41#define __MEM_GUARDEDALLOC_H__
84extern short (*MEM_testN)(
void *vmemh);
98extern void *(*MEM_reallocN_id)(
void *vmemh,
106extern void *(*MEM_recallocN_id)(
void *vmemh,
111#define MEM_reallocN(vmemh, len) MEM_reallocN_id(vmemh, len, __func__)
112#define MEM_recallocN(vmemh, len) MEM_recallocN_id(vmemh, len, __func__)
180# define MEM_SAFE_FREE(v) \
188# define MEM_SAFE_FREE(v) \
190 void **_v = (void **)&(v); \
250#define MEM_SIZE_OVERHEAD sizeof(size_t)
251#define MEM_SIZE_OPTIMAL(size) ((size)-MEM_SIZE_OVERHEAD)
254extern const char *(*MEM_name_ptr)(
void *vmemh);
318# include <type_traits>
328# define MEM_MIN_CPP_ALIGNMENT \
329 (__STDCPP_DEFAULT_NEW_ALIGNMENT__ < alignof(void *) ? __STDCPP_DEFAULT_NEW_ALIGNMENT__ : \
363template<
typename T,
typename... Args>
364inline T *MEM_new(
const char *allocation_name, Args &&...args)
368 return new (buffer)
T(std::forward<Args>(args)...);
380template<
typename T>
inline void MEM_delete(
const T *ptr)
384 "MEM_delete on a void pointer is not possible, `static_cast` it to the correct type");
385 if (ptr ==
nullptr) {
398# define MEM_SAFE_DELETE(v) \
407# define MEM_CXX_CLASS_ALLOC_FUNCS(_id) \
409 void *operator new(size_t num_bytes) \
411 return mem_guarded::internal::mem_mallocN_aligned_ex( \
413 __STDCPP_DEFAULT_NEW_ALIGNMENT__, \
415 mem_guarded::internal::AllocationType::NEW_DELETE); \
417 void *operator new(size_t num_bytes, std::align_val_t alignment) \
419 return mem_guarded::internal::mem_mallocN_aligned_ex( \
420 num_bytes, size_t(alignment), _id, mem_guarded::internal::AllocationType::NEW_DELETE); \
422 void operator delete(void *mem) \
425 mem_guarded::internal::mem_freeN_ex(mem, \
426 mem_guarded::internal::AllocationType::NEW_DELETE); \
429 void *operator new[](size_t num_bytes) \
431 return mem_guarded::internal::mem_mallocN_aligned_ex( \
433 __STDCPP_DEFAULT_NEW_ALIGNMENT__, \
435 mem_guarded::internal::AllocationType::NEW_DELETE); \
437 void *operator new[](size_t num_bytes, std::align_val_t alignment) \
439 return mem_guarded::internal::mem_mallocN_aligned_ex( \
443 mem_guarded::internal::AllocationType::NEW_DELETE); \
445 void operator delete[](void *mem) \
448 mem_guarded::internal::mem_freeN_ex(mem, \
449 mem_guarded::internal::AllocationType::NEW_DELETE); \
452 void *operator new(size_t , void *ptr) \
461 void operator delete(void * , void * ) {}
492template<
typename T>
inline T *
MEM_callocN(
const char *allocation_name)
495 static_assert(std::is_trivially_constructible_v<T>,
496 "For non-trivial types, MEM_new must be used.");
498 static_assert(std::is_trivial_v<T>,
"For non-trivial types, MEM_new must be used.");
511 static_assert(std::is_trivially_constructible_v<T>,
512 "For non-trivial types, MEM_new must be used.");
514 static_assert(std::is_trivial_v<T>,
"For non-trivial types, MEM_new must be used.");
516 return static_cast<T *
>(
531template<
typename T>
inline T *
MEM_mallocN(
const char *allocation_name)
534 static_assert(std::is_trivially_constructible_v<T>,
535 "For non-trivial types, MEM_new must be used.");
537 static_assert(std::is_trivial_v<T>,
"For non-trivial types, MEM_new must be used.");
550 static_assert(std::is_trivially_constructible_v<T>,
551 "For non-trivial types, MEM_new must be used.");
553 static_assert(std::is_trivial_v<T>,
"For non-trivial types, MEM_new must be used.");
555 return static_cast<T *
>(
570template<
typename T>
inline T *
MEM_dupallocN(
const char *allocation_name,
const T &other)
573 static_assert(std::is_trivially_constructible_v<T>,
574 "For non-trivial types, MEM_new must be used.");
576 static_assert(std::is_trivial_v<T>,
"For non-trivial types, MEM_new must be used.");
580 memcpy(new_object, &other,
sizeof(
T));
585template<
typename T>
inline void MEM_freeN(
T *ptr)
588 static_assert(std::is_trivially_destructible_v<T>,
589 "For non-trivial types, MEM_delete must be used.");
591 static_assert(std::is_trivial_v<T>,
"For non-trivial types, MEM_delete must be used.");
608template<
typename T,
typename... Args>
T &MEM_construct_leak_detection_data(Args &&...args)
610 std::shared_ptr<T>
data = std::make_shared<T>(std::forward<Args>(args)...);
611 std::any any_data = std::make_any<std::shared_ptr<T>>(
data);
#define ATTR_WARN_UNUSED_RESULT
#define ATTR_ALLOC_SIZE(...)
#define ATTR_NONNULL(...)
BMesh const char void * data
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
float length(VecOp< float, D >) RET
void MEM_use_memleak_detection(bool enabled)
void MEM_enable_fail_on_memleak()
void MEM_init_memleak_detection()
void * MEM_mallocN(size_t len, const char *str)
void *(*) MEM_malloc_arrayN_aligned(size_t len, size_t size, size_t alignment, const char *str)
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
void MEM_use_lockfree_allocator()
void(*) MEM_set_memory_debug(void)
void * MEM_mallocN_aligned(size_t len, size_t alignment, const char *str)
size_t(*) MEM_allocN_len(const void *vmemh)
bool(*) MEM_consistency_check(void)
size_t(*) MEM_get_memory_in_use(void)
void * MEM_callocN(size_t len, const char *str)
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
void * MEM_dupallocN(const void *vmemh)
void(*) MEM_printmemlist(void)
void(*) MEM_printmemlist_pydict(void)
uint(*) MEM_get_memory_blocks_in_use(void)
size_t(*) MEM_get_peak_memory(void)
void MEM_use_guarded_allocator()
void(*) MEM_name_ptr_set(void *vmemh, const char *str)
void MEM_freeN(void *vmemh)
void(*) MEM_set_error_callback(void(*func)(const char *))
void(*) MEM_reset_peak_memory(void)
void(*) MEM_callbackmemlist(void(*func)(void *))
void *(*) MEM_calloc_arrayN_aligned(size_t len, size_t size, size_t alignment, const char *str)
void(*) MEM_printmemlist_stats(void)
ccl_device_inline float len(const float2 a)
void(*) mem_freeN_ex(void *vmemh, AllocationType allocation_type)
void add_memleak_data(std::any data)
void *(*) mem_mallocN_aligned_ex(size_t len, size_t alignment, const char *str, AllocationType allocation_type)