Blender V4.5
MEM_guardedalloc.h
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
39
40#ifndef __MEM_GUARDEDALLOC_H__
41#define __MEM_GUARDEDALLOC_H__
42
43/* Needed for uintptr_t and attributes, exception, don't use BLI anywhere else in `MEM_*` */
46
47#include <string.h>
48
49#ifdef __cplusplus
50extern "C" {
51#endif
52
53/* -------------------------------------------------------------------- */
65
71extern size_t (*MEM_allocN_len)(const void *vmemh) ATTR_WARN_UNUSED_RESULT;
72
78void MEM_freeN(void *vmemh);
79
80#if 0 /* UNUSED */
84extern short (*MEM_testN)(void *vmemh);
85#endif
86
91void *MEM_dupallocN(const void *vmemh) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT;
92
98extern void *(*MEM_reallocN_id)(void *vmemh,
99 size_t len,
100 const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT
102
106extern void *(*MEM_recallocN_id)(void *vmemh,
107 size_t len,
108 const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT
110
111#define MEM_reallocN(vmemh, len) MEM_reallocN_id(vmemh, len, __func__)
112#define MEM_recallocN(vmemh, len) MEM_recallocN_id(vmemh, len, __func__)
113
119void *MEM_callocN(size_t len, const char *str) ATTR_WARN_UNUSED_RESULT ATTR_ALLOC_SIZE(1)
120 ATTR_NONNULL(2);
121
128 size_t size,
129 const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT
131
136void *MEM_mallocN(size_t len, const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT
138
145 size_t size,
146 const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT
148
153void *MEM_mallocN_aligned(size_t len,
154 size_t alignment,
155 const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT
157
161extern void *(*MEM_malloc_arrayN_aligned)(
162 size_t len,
163 size_t size,
164 size_t alignment,
165 const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT ATTR_ALLOC_SIZE(1, 2)
167
171extern void *(*MEM_calloc_arrayN_aligned)(
172 size_t len,
173 size_t size,
174 size_t alignment,
175 const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT ATTR_ALLOC_SIZE(1, 2)
176 ATTR_NONNULL(4);
177
178#ifdef __cplusplus
180# define MEM_SAFE_FREE(v) \
181 do { \
182 if (v) { \
183 MEM_freeN(v); \
184 (v) = nullptr; \
185 } \
186 } while (0)
187#else
188# define MEM_SAFE_FREE(v) \
189 do { \
190 void **_v = (void **)&(v); \
191 if (*_v) { \
192 MEM_freeN(*_v); \
193 *_v = NULL; \
194 } \
195 } while (0)
196#endif
197
199
200/* -------------------------------------------------------------------- */
207
212extern void (*MEM_printmemlist_pydict)(void);
213
217extern void (*MEM_printmemlist)(void);
218
220extern void (*MEM_callbackmemlist)(void (*func)(void *));
221
223extern void (*MEM_printmemlist_stats)(void);
224
226extern void (*MEM_set_error_callback)(void (*func)(const char *));
227
233extern bool (*MEM_consistency_check)(void);
234
236extern void (*MEM_set_memory_debug)(void);
237
239extern size_t (*MEM_get_memory_in_use)(void);
241extern unsigned int (*MEM_get_memory_blocks_in_use)(void);
242
244extern void (*MEM_reset_peak_memory)(void);
245
247extern size_t (*MEM_get_peak_memory)(void) ATTR_WARN_UNUSED_RESULT;
248
250#define MEM_SIZE_OVERHEAD sizeof(size_t)
251#define MEM_SIZE_OPTIMAL(size) ((size)-MEM_SIZE_OVERHEAD)
252
253#ifndef NDEBUG
254extern const char *(*MEM_name_ptr)(void *vmemh);
263extern void (*MEM_name_ptr_set)(void *vmemh, const char *str) ATTR_NONNULL();
264#endif
265
271
277
284
295
306
308
309#ifdef __cplusplus
310}
311#endif /* __cplusplus */
312
313#ifdef __cplusplus
314
315# include <any>
316# include <memory>
317# include <new>
318# include <type_traits>
319# include <utility>
320
322
328# define MEM_MIN_CPP_ALIGNMENT \
329 (__STDCPP_DEFAULT_NEW_ALIGNMENT__ < alignof(void *) ? __STDCPP_DEFAULT_NEW_ALIGNMENT__ : \
330 alignof(void *))
331
332/* -------------------------------------------------------------------- */
348
363template<typename T, typename... Args>
364inline T *MEM_new(const char *allocation_name, Args &&...args)
365{
367 sizeof(T), alignof(T), allocation_name, mem_guarded::internal::AllocationType::NEW_DELETE);
368 return new (buffer) T(std::forward<Args>(args)...);
369}
370
380template<typename T> inline void MEM_delete(const T *ptr)
381{
382 static_assert(
383 !std::is_void_v<T>,
384 "MEM_delete on a void pointer is not possible, `static_cast` it to the correct type");
385 if (ptr == nullptr) {
386 return;
387 }
388 /* C++ allows destruction of `const` objects, so the pointer is allowed to be `const`. */
389 ptr->~T();
392}
393
398# define MEM_SAFE_DELETE(v) \
399 do { \
400 if (v) { \
401 MEM_delete(v); \
402 (v) = nullptr; \
403 } \
404 } while (0)
405
407# define MEM_CXX_CLASS_ALLOC_FUNCS(_id) \
408 public: \
409 void *operator new(size_t num_bytes) \
410 { \
411 return mem_guarded::internal::mem_mallocN_aligned_ex( \
412 num_bytes, \
413 __STDCPP_DEFAULT_NEW_ALIGNMENT__, \
414 _id, \
415 mem_guarded::internal::AllocationType::NEW_DELETE); \
416 } \
417 void *operator new(size_t num_bytes, std::align_val_t alignment) \
418 { \
419 return mem_guarded::internal::mem_mallocN_aligned_ex( \
420 num_bytes, size_t(alignment), _id, mem_guarded::internal::AllocationType::NEW_DELETE); \
421 } \
422 void operator delete(void *mem) \
423 { \
424 if (mem) { \
425 mem_guarded::internal::mem_freeN_ex(mem, \
426 mem_guarded::internal::AllocationType::NEW_DELETE); \
427 } \
428 } \
429 void *operator new[](size_t num_bytes) \
430 { \
431 return mem_guarded::internal::mem_mallocN_aligned_ex( \
432 num_bytes, \
433 __STDCPP_DEFAULT_NEW_ALIGNMENT__, \
434 _id "[]", \
435 mem_guarded::internal::AllocationType::NEW_DELETE); \
436 } \
437 void *operator new[](size_t num_bytes, std::align_val_t alignment) \
438 { \
439 return mem_guarded::internal::mem_mallocN_aligned_ex( \
440 num_bytes, \
441 size_t(alignment), \
442 _id "[]", \
443 mem_guarded::internal::AllocationType::NEW_DELETE); \
444 } \
445 void operator delete[](void *mem) \
446 { \
447 if (mem) { \
448 mem_guarded::internal::mem_freeN_ex(mem, \
449 mem_guarded::internal::AllocationType::NEW_DELETE); \
450 } \
451 } \
452 void *operator new(size_t /*count*/, void *ptr) \
453 { \
454 return ptr; \
455 } \
456 \
461 void operator delete(void * /*ptr_to_free*/, void * /*ptr*/) {}
462
464
465/* -------------------------------------------------------------------- */
480
492template<typename T> inline T *MEM_callocN(const char *allocation_name)
493{
494# ifdef _MSC_VER
495 static_assert(std::is_trivially_constructible_v<T>,
496 "For non-trivial types, MEM_new must be used.");
497# else
498 static_assert(std::is_trivial_v<T>, "For non-trivial types, MEM_new must be used.");
499# endif
500 return static_cast<T *>(MEM_calloc_arrayN_aligned(1, sizeof(T), alignof(T), allocation_name));
501}
502
508template<typename T> inline T *MEM_calloc_arrayN(const size_t length, const char *allocation_name)
509{
510# ifdef _MSC_VER
511 static_assert(std::is_trivially_constructible_v<T>,
512 "For non-trivial types, MEM_new must be used.");
513# else
514 static_assert(std::is_trivial_v<T>, "For non-trivial types, MEM_new must be used.");
515# endif
516 return static_cast<T *>(
517 MEM_calloc_arrayN_aligned(length, sizeof(T), alignof(T), allocation_name));
518}
519
531template<typename T> inline T *MEM_mallocN(const char *allocation_name)
532{
533# ifdef _MSC_VER
534 static_assert(std::is_trivially_constructible_v<T>,
535 "For non-trivial types, MEM_new must be used.");
536# else
537 static_assert(std::is_trivial_v<T>, "For non-trivial types, MEM_new must be used.");
538# endif
539 return static_cast<T *>(MEM_malloc_arrayN_aligned(1, sizeof(T), alignof(T), allocation_name));
540}
541
547template<typename T> inline T *MEM_malloc_arrayN(const size_t length, const char *allocation_name)
548{
549# ifdef _MSC_VER
550 static_assert(std::is_trivially_constructible_v<T>,
551 "For non-trivial types, MEM_new must be used.");
552# else
553 static_assert(std::is_trivial_v<T>, "For non-trivial types, MEM_new must be used.");
554# endif
555 return static_cast<T *>(
556 MEM_malloc_arrayN_aligned(length, sizeof(T), alignof(T), allocation_name));
557}
558
570template<typename T> inline T *MEM_dupallocN(const char *allocation_name, const T &other)
571{
572# ifdef _MSC_VER
573 static_assert(std::is_trivially_constructible_v<T>,
574 "For non-trivial types, MEM_new must be used.");
575# else
576 static_assert(std::is_trivial_v<T>, "For non-trivial types, MEM_new must be used.");
577# endif
578 T *new_object = static_cast<T *>(MEM_mallocN_aligned(sizeof(T), alignof(T), allocation_name));
579 if (new_object) {
580 memcpy(new_object, &other, sizeof(T));
581 }
582 return new_object;
583}
584
585template<typename T> inline void MEM_freeN(T *ptr)
586{
587# ifdef _MSC_VER
588 static_assert(std::is_trivially_destructible_v<T>,
589 "For non-trivial types, MEM_delete must be used.");
590# else
591 static_assert(std::is_trivial_v<T>, "For non-trivial types, MEM_delete must be used.");
592# endif
593 mem_guarded::internal::mem_freeN_ex(const_cast<void *>(static_cast<const void *>(ptr)),
595}
596
598
608template<typename T, typename... Args> T &MEM_construct_leak_detection_data(Args &&...args)
609{
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);
613 return *data;
614}
615
616#endif /* __cplusplus */
617
618#endif /* __MEM_GUARDEDALLOC_H__ */
#define ATTR_WARN_UNUSED_RESULT
#define ATTR_ALLOC_SIZE(...)
#define ATTR_NONNULL(...)
void MEM_use_guarded_allocator(void)
Definition mallocn.cc:204
void MEM_use_memleak_detection(bool enabled)
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
Definition mallocn.cc:55
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)
Definition mallocn.cc:118
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
Definition mallocn.cc:59
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)
Definition mallocn.cc:138
void MEM_use_lockfree_allocator(void)
Definition mallocn.cc:163
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
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)
Definition mallocn.cc:128
void * MEM_dupallocN(const void *vmemh) ATTR_WARN_UNUSED_RESULT
Definition mallocn.cc:143
BMesh const char void * data
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
#define str(s)
float length(VecOp< float, D >) RET
bool enabled
void * MEM_mallocN(size_t len, const char *str)
Definition mallocn.cc:128
size_t(* MEM_get_peak_memory)(void)
Definition mallocn.cc:73
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
void * MEM_mallocN_aligned(size_t len, size_t alignment, const char *str)
Definition mallocn.cc:138
void(* MEM_reset_peak_memory)(void)
Definition mallocn.cc:72
void(* MEM_name_ptr_set)(void *vmemh, const char *str)
Definition mallocn.cc:79
size_t(* MEM_get_memory_in_use)(void)
Definition mallocn.cc:70
void *(* MEM_calloc_arrayN_aligned)(size_t len, size_t size, size_t alignment, const char *str)
Definition mallocn.cc:59
void(* MEM_printmemlist_stats)(void)
Definition mallocn.cc:66
void(* MEM_set_memory_debug)(void)
Definition mallocn.cc:69
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
void(* MEM_set_error_callback)(void(*func)(const char *))
Definition mallocn.cc:67
size_t(* MEM_allocN_len)(const void *vmemh)
Definition mallocn.cc:36
bool(* MEM_consistency_check)(void)
Definition mallocn.cc:68
void *(* MEM_malloc_arrayN_aligned)(size_t len, size_t size, size_t alignment, const char *str)
Definition mallocn.cc:55
void(* MEM_printmemlist_pydict)(void)
Definition mallocn.cc:63
uint(* MEM_get_memory_blocks_in_use)(void)
Definition mallocn.cc:71
void(* MEM_callbackmemlist)(void(*func)(void *))
Definition mallocn.cc:65
void(* MEM_printmemlist)(void)
Definition mallocn.cc:64
#define T
void add_memleak_data(std::any data)
void(* mem_freeN_ex)(void *vmemh, AllocationType allocation_type)
Definition mallocn.cc:37
void *(* mem_mallocN_aligned_ex)(size_t len, size_t alignment, const char *str, AllocationType allocation_type)
Definition mallocn.cc:50
uint len
PointerRNA * ptr
Definition wm_files.cc:4227