MEM_guardedalloc: Add template 'type-safe' versions of MEM_mallocN.
Same thing as for `MEM_callocN<T>` and `MEM_freeN<T>` in dd168a35c5,
allows to reduce type verbosity, and increase type safety.
This commit is contained in:
committed by
Bastien Montagne
parent
82e2a57dcd
commit
2900cfa50a
@@ -114,7 +114,7 @@ void *MEM_calloc_arrayN(size_t len,
|
||||
* Allocate a block of memory of size len, with tag name str. The
|
||||
* name must be a static, because only a pointer to it is stored!
|
||||
*/
|
||||
extern void *(*MEM_mallocN)(size_t len, const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT
|
||||
void *MEM_mallocN(size_t len, const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT
|
||||
ATTR_ALLOC_SIZE(1) ATTR_NONNULL(2);
|
||||
|
||||
/**
|
||||
@@ -122,9 +122,9 @@ extern void *(*MEM_mallocN)(size_t len, const char *str) /* ATTR_MALLOC */ ATTR_
|
||||
* aborting in case of integer overflow to prevent vulnerabilities. The
|
||||
* name must be a static, because only a pointer to it is stored!
|
||||
*/
|
||||
extern void *(*MEM_malloc_arrayN)(size_t len,
|
||||
size_t size,
|
||||
const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT
|
||||
void *MEM_malloc_arrayN(size_t len,
|
||||
size_t size,
|
||||
const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT
|
||||
ATTR_ALLOC_SIZE(1, 2) ATTR_NONNULL(3);
|
||||
|
||||
/**
|
||||
@@ -403,6 +403,55 @@ template<typename T> inline T *MEM_calloc_arrayN(const size_t length, const char
|
||||
MEM_calloc_arrayN_aligned(length, sizeof(T), alignof(T), allocation_name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate uninitialized memory for an object of type #T. The constructor of #T is not called,
|
||||
* therefore this must only be used with trivial types (like all C types).
|
||||
*
|
||||
* When allocating an enforced specific amount of bytes, the C version of this function should be
|
||||
* used instead. While this should be avoided in C++ code, it is still required in some cases, e.g.
|
||||
* for ID allocation based on #IDTypeInfo::struct_size.
|
||||
*
|
||||
* #MEM_freeN must be used to free a pointer returned by this call. Calling #MEM_delete on it is
|
||||
* illegal.
|
||||
*/
|
||||
template<typename T> inline T *MEM_mallocN(const char *allocation_name)
|
||||
{
|
||||
# ifdef _MSC_VER
|
||||
/* MSVC considers C-style types using the DNA_DEFINE_CXX_METHODS as non-trivial (more
|
||||
* specifically, non-trivially copyable, likely because the default copy constructors are
|
||||
* deleted). GCC and clang (both on linux, OSX, and clang-cl on Windows on Arm) do not.
|
||||
*
|
||||
* So for now, use a more restricted check on MSVC, should still catch most of actual invalid
|
||||
* cases. */
|
||||
static_assert(std::is_trivially_constructible_v<T>,
|
||||
"For non-trivial types, MEM_new must be used.");
|
||||
# else
|
||||
static_assert(std::is_trivial_v<T>, "For non-trivial types, MEM_new must be used.");
|
||||
# endif
|
||||
return static_cast<T *>(MEM_malloc_arrayN_aligned(1, sizeof(T), alignof(T), allocation_name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Type-safe version of #MEM_malloc_arrayN/#MEM_malloc_array_alignedN.
|
||||
*/
|
||||
template<typename T> inline T *MEM_malloc_arrayN(const size_t length, const char *allocation_name)
|
||||
{
|
||||
# ifdef _MSC_VER
|
||||
/* MSVC considers C-style types using the DNA_DEFINE_CXX_METHODS as non-trivial (more
|
||||
* specifically, non-trivially copyable, likely because the default copy constructors are
|
||||
* deleted). GCC and clang (both on linux, OSX, and clang-cl on Windows on Arm) do not.
|
||||
*
|
||||
* So for now, use a more restricted check on MSVC, should still catch most of actual invalid
|
||||
* cases. */
|
||||
static_assert(std::is_trivially_constructible_v<T>,
|
||||
"For non-trivial types, MEM_new must be used.");
|
||||
# else
|
||||
static_assert(std::is_trivial_v<T>, "For non-trivial types, MEM_new must be used.");
|
||||
# endif
|
||||
return static_cast<T *>(
|
||||
MEM_malloc_arrayN_aligned(length, sizeof(T), alignof(T), allocation_name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate memory for an object of type #T and memory-copy `other` into it.
|
||||
* Only applicable for trivial types.
|
||||
|
||||
@@ -43,8 +43,10 @@ void *(*mem_guarded::internal::mem_callocN)(size_t len, const char *str) = MEM_l
|
||||
void *(*mem_guarded::internal::mem_calloc_arrayN)(size_t len,
|
||||
size_t size,
|
||||
const char *str) = MEM_lockfree_calloc_arrayN;
|
||||
void *(*MEM_mallocN)(size_t len, const char *str) = MEM_lockfree_mallocN;
|
||||
void *(*MEM_malloc_arrayN)(size_t len, size_t size, const char *str) = MEM_lockfree_malloc_arrayN;
|
||||
void *(*mem_guarded::internal::mem_mallocN)(size_t len, const char *str) = MEM_lockfree_mallocN;
|
||||
void *(*mem_guarded::internal::mem_malloc_arrayN)(size_t len,
|
||||
size_t size,
|
||||
const char *str) = MEM_lockfree_malloc_arrayN;
|
||||
void *(*mem_guarded::internal::mem_mallocN_aligned_ex)(size_t len,
|
||||
size_t alignment,
|
||||
const char *str,
|
||||
@@ -123,6 +125,16 @@ void *MEM_calloc_arrayN(size_t len, size_t size, const char *str)
|
||||
return mem_calloc_arrayN(len, size, str);
|
||||
}
|
||||
|
||||
void *MEM_mallocN(size_t len, const char *str)
|
||||
{
|
||||
return mem_mallocN(len, str);
|
||||
}
|
||||
|
||||
void *MEM_malloc_arrayN(size_t len, size_t size, const char *str)
|
||||
{
|
||||
return mem_malloc_arrayN(len, size, str);
|
||||
}
|
||||
|
||||
void *MEM_mallocN_aligned(size_t len, size_t alignment, const char *str)
|
||||
{
|
||||
return mem_mallocN_aligned_ex(len, alignment, str, AllocationType::ALLOC_FREE);
|
||||
@@ -164,8 +176,8 @@ void MEM_use_lockfree_allocator()
|
||||
MEM_recallocN_id = MEM_lockfree_recallocN_id;
|
||||
mem_callocN = MEM_lockfree_callocN;
|
||||
mem_calloc_arrayN = MEM_lockfree_calloc_arrayN;
|
||||
MEM_mallocN = MEM_lockfree_mallocN;
|
||||
MEM_malloc_arrayN = MEM_lockfree_malloc_arrayN;
|
||||
mem_mallocN = MEM_lockfree_mallocN;
|
||||
mem_malloc_arrayN = MEM_lockfree_malloc_arrayN;
|
||||
mem_mallocN_aligned_ex = MEM_lockfree_mallocN_aligned;
|
||||
MEM_malloc_arrayN_aligned = MEM_lockfree_malloc_arrayN_aligned;
|
||||
MEM_calloc_arrayN_aligned = MEM_lockfree_calloc_arrayN_aligned;
|
||||
@@ -200,8 +212,8 @@ void MEM_use_guarded_allocator()
|
||||
MEM_recallocN_id = MEM_guarded_recallocN_id;
|
||||
mem_callocN = MEM_guarded_callocN;
|
||||
mem_calloc_arrayN = MEM_guarded_calloc_arrayN;
|
||||
MEM_mallocN = MEM_guarded_mallocN;
|
||||
MEM_malloc_arrayN = MEM_guarded_malloc_arrayN;
|
||||
mem_mallocN = MEM_guarded_mallocN;
|
||||
mem_malloc_arrayN = MEM_guarded_malloc_arrayN;
|
||||
mem_mallocN_aligned_ex = MEM_guarded_mallocN_aligned;
|
||||
MEM_malloc_arrayN_aligned = MEM_guarded_malloc_arrayN_aligned;
|
||||
MEM_calloc_arrayN_aligned = MEM_guarded_calloc_arrayN_aligned;
|
||||
|
||||
@@ -720,7 +720,7 @@ static void *mem_guarded_malloc_arrayN_aligned(const size_t len,
|
||||
return nullptr;
|
||||
}
|
||||
if (alignment <= MEM_MIN_CPP_ALIGNMENT) {
|
||||
return mem_callocN(r_bytes_num, str);
|
||||
return mem_mallocN(r_bytes_num, str);
|
||||
}
|
||||
return MEM_mallocN_aligned(r_bytes_num, alignment, str);
|
||||
}
|
||||
|
||||
@@ -36,6 +36,22 @@ extern void *(*mem_calloc_arrayN)(size_t len,
|
||||
const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT
|
||||
ATTR_ALLOC_SIZE(1, 2) ATTR_NONNULL(3);
|
||||
|
||||
/**
|
||||
* Internal implementation of #MEM_mallocN, exposed because public #MEM_mallocN cannot be a
|
||||
* function pointer, to allow its overload by C++ template version.
|
||||
*/
|
||||
extern void *(*mem_mallocN)(size_t len, const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT
|
||||
ATTR_ALLOC_SIZE(1) ATTR_NONNULL(2);
|
||||
|
||||
/**
|
||||
* Internal implementation of #MEM_malloc_arrayN, exposed because public #MEM_malloc_arrayN cannot
|
||||
* be a function pointer, to allow its overload by C++ template version.
|
||||
*/
|
||||
extern void *(*mem_malloc_arrayN)(size_t len,
|
||||
size_t size,
|
||||
const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT
|
||||
ATTR_ALLOC_SIZE(1, 2) ATTR_NONNULL(3);
|
||||
|
||||
/** Internal implementation of #MEM_mallocN_aligned, exposed because #MEM_new needs access to it.
|
||||
*/
|
||||
extern void *(*mem_mallocN_aligned_ex)(size_t len,
|
||||
|
||||
@@ -474,7 +474,7 @@ static void *mem_lockfree_malloc_arrayN_aligned(const size_t len,
|
||||
return nullptr;
|
||||
}
|
||||
if (alignment <= MEM_MIN_CPP_ALIGNMENT) {
|
||||
return mem_callocN(r_bytes_num, str);
|
||||
return mem_mallocN(r_bytes_num, str);
|
||||
}
|
||||
void *ptr = MEM_mallocN_aligned(r_bytes_num, alignment, str);
|
||||
return ptr;
|
||||
|
||||
Reference in New Issue
Block a user