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) \
189struct MEM_freeN_smart_ptr_deleter {
197# define MEM_SAFE_FREE(v) \
199 void **_v = (void **)&(v); \
259#define MEM_SIZE_OVERHEAD sizeof(size_t)
260#define MEM_SIZE_OPTIMAL(size) ((size) - MEM_SIZE_OVERHEAD)
263extern const char *(*MEM_name_ptr)(
void *vmemh);
321# include <type_traits>
331# define MEM_MIN_CPP_ALIGNMENT \
332 (__STDCPP_DEFAULT_NEW_ALIGNMENT__ < alignof(void *) ? __STDCPP_DEFAULT_NEW_ALIGNMENT__ : \
355constexpr bool is_trivial_after_construction = std::is_trivially_copyable_v<T> &&
356 std::is_trivially_destructible_v<T>;
373template<
typename T,
typename... Args>
374inline T *MEM_new(
const char *allocation_name, Args &&...args)
378 return new (buffer)
T(std::forward<Args>(args)...);
402template<
typename T>
inline T *MEM_new_for_free(
const char *allocation_name)
404 static_assert(mem_guarded::internal::is_trivial_after_construction<T>,
405 "MEM_new_for_free can only construct types that are trivially copyable and "
406 "destructible, use MEM_new instead.");
410 if (
alignof(
T) <= MEM_MIN_CPP_ALIGNMENT) {
416 memset(buffer, 0,
sizeof(
T));
418 return new (buffer)
T;
430template<
typename T>
inline void MEM_delete(
const T *
ptr)
434 "MEM_delete on a void pointer is not possible, `static_cast` it to the correct type");
435 if (
ptr ==
nullptr) {
438 const void *complete_ptr = [
ptr]() {
439 if constexpr (std::is_polymorphic_v<T>) {
446 return dynamic_cast<const void *
>(
ptr);
449 return static_cast<const void *
>(
ptr);
462# define MEM_SAFE_DELETE(v) \
471# define MEM_CXX_CLASS_ALLOC_FUNCS(_id) \
473 void *operator new(size_t num_bytes) \
475 return mem_guarded::internal::mem_mallocN_aligned_ex( \
477 __STDCPP_DEFAULT_NEW_ALIGNMENT__, \
479 mem_guarded::internal::AllocationType::NEW_DELETE); \
481 void *operator new(size_t num_bytes, std::align_val_t alignment) \
483 return mem_guarded::internal::mem_mallocN_aligned_ex( \
484 num_bytes, size_t(alignment), _id, mem_guarded::internal::AllocationType::NEW_DELETE); \
486 void operator delete(void *mem) \
489 mem_guarded::internal::mem_freeN_ex(mem, \
490 mem_guarded::internal::AllocationType::NEW_DELETE); \
493 void *operator new[](size_t num_bytes) \
495 return mem_guarded::internal::mem_mallocN_aligned_ex( \
497 __STDCPP_DEFAULT_NEW_ALIGNMENT__, \
499 mem_guarded::internal::AllocationType::NEW_DELETE); \
501 void *operator new[](size_t num_bytes, std::align_val_t alignment) \
503 return mem_guarded::internal::mem_mallocN_aligned_ex( \
507 mem_guarded::internal::AllocationType::NEW_DELETE); \
509 void operator delete[](void *mem) \
512 mem_guarded::internal::mem_freeN_ex(mem, \
513 mem_guarded::internal::AllocationType::NEW_DELETE); \
516 void *operator new(size_t , void *ptr) \
525 void operator delete(void * , void * ) {}
556template<
typename T>
inline T *
MEM_callocN(
const char *allocation_name)
559 static_assert(std::is_trivially_constructible_v<T>,
560 "For non-trivial types, MEM_new must be used.");
562 static_assert(std::is_trivial_v<T>,
"For non-trivial types, MEM_new must be used.");
575 static_assert(std::is_trivially_constructible_v<T>,
576 "For non-trivial types, MEM_new must be used.");
578 static_assert(std::is_trivial_v<T>,
"For non-trivial types, MEM_new must be used.");
580 return static_cast<T *
>(
595template<
typename T>
inline T *
MEM_mallocN(
const char *allocation_name)
598 static_assert(std::is_trivially_constructible_v<T>,
599 "For non-trivial types, MEM_new must be used.");
601 static_assert(std::is_trivial_v<T>,
"For non-trivial types, MEM_new must be used.");
614 static_assert(std::is_trivially_constructible_v<T>,
615 "For non-trivial types, MEM_new must be used.");
617 static_assert(std::is_trivial_v<T>,
"For non-trivial types, MEM_new must be used.");
619 return static_cast<T *
>(
634template<
typename T>
inline T *
MEM_dupallocN(
const char *allocation_name,
const T &other)
637 static_assert(std::is_trivially_assignable_v<T &, T> && std::is_trivially_destructible_v<T>,
638 "MEM_dupallocN can only duplicate types that are trivially copyable and "
639 "destructible, use MEM_new instead.");
641 static_assert(mem_guarded::internal::is_trivial_after_construction<T>,
642 "MEM_dupallocN can only duplicate types that are trivially copyable and "
643 "destructible, use MEM_new instead.");
647 memcpy(new_object, &other,
sizeof(
T));
655 static_assert(std::is_trivially_destructible_v<T>,
656 "MEM_freeN can only free types that are trivially copyable and destructible, use "
657 "MEM_delete instead.");
659 static_assert(mem_guarded::internal::is_trivial_after_construction<T>,
660 "MEM_freeN can only free types that are trivially copyable and destructible, use "
661 "MEM_delete instead.");
678template<
typename T,
typename... Args>
T &MEM_construct_leak_detection_data(Args &&...args)
680 std::shared_ptr<T>
data = std::make_shared<T>(std::forward<Args>(args)...);
681 std::any any_data = std::make_any<std::shared_ptr<T>>(
data);
#define ATTR_WARN_UNUSED_RESULT
#define ATTR_ALLOC_SIZE(...)
#define ATTR_NONNULL(...)
void MEM_use_guarded_allocator(void)
void *(* MEM_malloc_arrayN_aligned)(size_t len, size_t size, size_t alignment, const char *str) ATTR_WARN_UNUSED_RESULT ATTR_ALLOC_SIZE(1
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str) ATTR_WARN_UNUSED_RESULT ATTR_ALLOC_SIZE(1
void MEM_enable_fail_on_memleak(void)
void * MEM_callocN(size_t len, const char *str) ATTR_WARN_UNUSED_RESULT ATTR_ALLOC_SIZE(1) ATTR_NONNULL(2)
void *(* MEM_calloc_arrayN_aligned)(size_t len, size_t size, size_t alignment, const char *str) ATTR_WARN_UNUSED_RESULT ATTR_ALLOC_SIZE(1
void MEM_init_memleak_detection(void)
void * MEM_mallocN_aligned(size_t len, size_t alignment, const char *str) ATTR_WARN_UNUSED_RESULT ATTR_ALLOC_SIZE(1) ATTR_NONNULL(3)
void MEM_use_lockfree_allocator(void)
void MEM_freeN(void *vmemh)
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str) ATTR_WARN_UNUSED_RESULT ATTR_ALLOC_SIZE(1
void * MEM_mallocN(size_t len, const char *str) ATTR_WARN_UNUSED_RESULT ATTR_ALLOC_SIZE(1) ATTR_NONNULL(2)
void * MEM_dupallocN(const void *vmemh) ATTR_WARN_UNUSED_RESULT
BMesh const char void * data
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
float length(VecOp< float, D >) RET
void * MEM_mallocN(size_t len, const char *str)
size_t(* MEM_get_peak_memory)(void)
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
void * MEM_mallocN_aligned(size_t len, size_t alignment, const char *str)
void(* MEM_reset_peak_memory)(void)
void(* MEM_name_ptr_set)(void *vmemh, const char *str)
size_t(* MEM_get_memory_in_use)(void)
void *(* MEM_calloc_arrayN_aligned)(size_t len, size_t size, size_t alignment, const char *str)
void(* MEM_printmemlist_stats)(void)
void(* MEM_set_memory_debug)(void)
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
void(* MEM_set_error_callback)(void(*func)(const char *))
size_t(* MEM_allocN_len)(const void *vmemh)
bool(* MEM_consistency_check)(void)
void *(* MEM_malloc_arrayN_aligned)(size_t len, size_t size, size_t alignment, const char *str)
void(* MEM_printmemlist_pydict)(void)
uint(* MEM_get_memory_blocks_in_use)(void)
void(* MEM_callbackmemlist)(void(*func)(void *))
void(* MEM_printmemlist)(void)
void add_memleak_data(std::any data)
void(* mem_freeN_ex)(void *vmemh, AllocationType allocation_type)
void *(* mem_mallocN_aligned_ex)(size_t len, size_t alignment, const char *str, AllocationType allocation_type)