MEM_guardedalloc: Refactor to add more type-safety.
The main goal of these changes are to improve static (i.e. build-time) checks on whether a given data can be allocated and freed with `malloc` and `free` (C-style), or requires proper C++-style construction and destruction (`new` and `delete`). * Add new `MEM_malloc_arrayN_aligned` API. * Make `MEM_freeN` a template function in C++, which does static assert on type triviality. * Add `MEM_SAFE_DELETE`, similar to `MEM_SAFE_FREE` but calling `MEM_delete`. The changes to `MEM_freeN` was painful and useful, as it allowed to fix a bunch of invalid calls in existing codebase already. It also highlighted a fair amount of places where it is called to free incomplete type pointers, which is likely a sign of badly designed code (there should rather be an API to destroy and free these data then, if the data type is not fully publicly exposed). For now, these are 'worked around' by explicitly casting the freed pointers to `void *` in these cases - which also makes them easy to search for. Some of these will be addressed separately (see blender/blender!134765). Finally, MSVC seems to consider structs defining new/delete operators (e.g. by using the `MEM_CXX_CLASS_ALLOC_FUNCS` macro) as non-trivial. This does not seem to follow the definition of type triviality, so for now static type checking in `MEM_freeN` has been disabled for Windows. We'll likely have to do the same with type-safe `MEM_[cm]allocN` API being worked on in blender/blender!134771 Based on ideas from Brecht in blender/blender!134452 Pull Request: https://projects.blender.org/blender/blender/pulls/134463
This commit is contained in:
committed by
Bastien Montagne
parent
6be8dd16e7
commit
48e26c3afe
@@ -61,7 +61,7 @@ template<typename T> class GuardedAllocator {
|
||||
util_guarded_mem_free(n * sizeof(T));
|
||||
if (p != nullptr) {
|
||||
#ifdef WITH_BLENDER_GUARDEDALLOC
|
||||
MEM_freeN(p);
|
||||
MEM_freeN(const_cast<void *>(static_cast<const void *>(p)));
|
||||
#else
|
||||
free(p);
|
||||
#endif
|
||||
|
||||
@@ -69,7 +69,7 @@ template<int SIZE, typename T> class ccl_try_align(16) StackAllocator
|
||||
if (p < data_ || p >= data_ + SIZE) {
|
||||
util_guarded_mem_free(n * sizeof(T));
|
||||
#ifdef WITH_BLENDER_GUARDEDALLOC
|
||||
MEM_freeN(p);
|
||||
MEM_freeN(static_cast<void *>(p));
|
||||
#else
|
||||
free(p);
|
||||
#endif
|
||||
|
||||
@@ -136,6 +136,16 @@ void *MEM_mallocN_aligned(size_t len,
|
||||
const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT
|
||||
ATTR_ALLOC_SIZE(1) ATTR_NONNULL(3);
|
||||
|
||||
/**
|
||||
* Allocate an aligned block of memory that remains uninitialized.
|
||||
*/
|
||||
extern void *(*MEM_malloc_arrayN_aligned)(
|
||||
size_t len,
|
||||
size_t size,
|
||||
size_t alignment,
|
||||
const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT ATTR_ALLOC_SIZE(1, 2)
|
||||
ATTR_NONNULL(4);
|
||||
|
||||
/**
|
||||
* Allocate an aligned block of memory that is initialized with zeros.
|
||||
*/
|
||||
@@ -190,11 +200,9 @@ extern size_t (*MEM_get_peak_memory)(void) ATTR_WARN_UNUSED_RESULT;
|
||||
#ifdef __cplusplus
|
||||
# define MEM_SAFE_FREE(v) \
|
||||
do { \
|
||||
static_assert(std::is_pointer_v<std::decay_t<decltype(v)>>); \
|
||||
void **_v = (void **)&(v); \
|
||||
if (*_v) { \
|
||||
MEM_freeN(*_v); \
|
||||
*_v = NULL; \
|
||||
if (v) { \
|
||||
MEM_freeN<std::remove_pointer_t<std::decay_t<decltype(v)>>>(v); \
|
||||
(v) = nullptr; \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
@@ -334,6 +342,18 @@ template<typename T> inline void MEM_delete(const T *ptr)
|
||||
mem_guarded::internal::AllocationType::NEW_DELETE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper shortcut to #MEM_delete, that also ensures that the target pointer is set to nullptr
|
||||
* after deleting it.
|
||||
*/
|
||||
# define MEM_SAFE_DELETE(v) \
|
||||
do { \
|
||||
if (v) { \
|
||||
MEM_delete(v); \
|
||||
(v) = nullptr; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* Allocate zero-initialized memory for an object of type #T. The constructor of #T is not called,
|
||||
* therefore this should only be used with trivial types (like all C types).
|
||||
@@ -377,6 +397,25 @@ template<typename T> inline T *MEM_cnew(const char *allocation_name, const T &ot
|
||||
return new_object;
|
||||
}
|
||||
|
||||
template<typename T> inline void MEM_freeN(T *ptr)
|
||||
{
|
||||
if constexpr (std::is_void_v<T>) {
|
||||
mem_guarded::internal::mem_freeN_ex(const_cast<void *>(ptr),
|
||||
mem_guarded::internal::AllocationType::ALLOC_FREE);
|
||||
}
|
||||
else {
|
||||
# ifndef _WIN32
|
||||
/* MSVC seems to consider C-style types using the MEM_CXX_CLASS_ALLOC_FUNCS as non-trivial. GCC
|
||||
* and clang (both on linux and OSX) do not.
|
||||
*
|
||||
* So for now, disable the triviality check on Windows. */
|
||||
static_assert(std::is_trivial_v<T>, "For non-trivial types, MEM_delete must be used.");
|
||||
# endif
|
||||
mem_guarded::internal::mem_freeN_ex(const_cast<void *>(static_cast<const void *>(ptr)),
|
||||
mem_guarded::internal::AllocationType::ALLOC_FREE);
|
||||
}
|
||||
}
|
||||
|
||||
/** Allocation functions (for C++ only). */
|
||||
# define MEM_CXX_CLASS_ALLOC_FUNCS(_id) \
|
||||
public: \
|
||||
|
||||
@@ -48,6 +48,10 @@ void *(*mem_guarded::internal::mem_mallocN_aligned_ex)(size_t len,
|
||||
const char *str,
|
||||
AllocationType allocation_type) =
|
||||
MEM_lockfree_mallocN_aligned;
|
||||
void *(*MEM_malloc_arrayN_aligned)(size_t len,
|
||||
size_t size,
|
||||
size_t alignment,
|
||||
const char *str) = MEM_lockfree_malloc_arrayN_aligned;
|
||||
void *(*MEM_calloc_arrayN_aligned)(size_t len,
|
||||
size_t size,
|
||||
size_t alignment,
|
||||
@@ -146,6 +150,7 @@ void MEM_use_lockfree_allocator()
|
||||
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;
|
||||
MEM_printmemlist_pydict = MEM_lockfree_printmemlist_pydict;
|
||||
MEM_printmemlist = MEM_lockfree_printmemlist;
|
||||
@@ -181,6 +186,7 @@ void MEM_use_guarded_allocator()
|
||||
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;
|
||||
MEM_printmemlist_pydict = MEM_guarded_printmemlist_pydict;
|
||||
MEM_printmemlist = MEM_guarded_printmemlist;
|
||||
|
||||
@@ -702,13 +702,13 @@ void *MEM_guarded_calloc_arrayN(size_t len, size_t size, const char *str)
|
||||
return MEM_guarded_callocN(total_size, str);
|
||||
}
|
||||
|
||||
void *MEM_guarded_calloc_arrayN_aligned(const size_t len,
|
||||
const size_t size,
|
||||
const size_t alignment,
|
||||
const char *str)
|
||||
static void *mem_guarded_malloc_arrayN_aligned(const size_t len,
|
||||
const size_t size,
|
||||
const size_t alignment,
|
||||
const char *str,
|
||||
size_t &r_bytes_num)
|
||||
{
|
||||
size_t bytes_num;
|
||||
if (UNLIKELY(!MEM_size_safe_multiply(len, size, &bytes_num))) {
|
||||
if (UNLIKELY(!MEM_size_safe_multiply(len, size, &r_bytes_num))) {
|
||||
print_error(
|
||||
"Calloc array aborted due to integer overflow: "
|
||||
"len=" SIZET_FORMAT "x" SIZET_FORMAT " in %s, total " SIZET_FORMAT "\n",
|
||||
@@ -720,11 +720,29 @@ void *MEM_guarded_calloc_arrayN_aligned(const size_t len,
|
||||
return nullptr;
|
||||
}
|
||||
if (alignment <= MEM_MIN_CPP_ALIGNMENT) {
|
||||
return MEM_callocN(bytes_num, str);
|
||||
return MEM_callocN(r_bytes_num, str);
|
||||
}
|
||||
return MEM_mallocN_aligned(r_bytes_num, alignment, str);
|
||||
}
|
||||
|
||||
void *MEM_guarded_malloc_arrayN_aligned(const size_t len,
|
||||
const size_t size,
|
||||
const size_t alignment,
|
||||
const char *str)
|
||||
{
|
||||
size_t bytes_num;
|
||||
return mem_guarded_malloc_arrayN_aligned(len, size, alignment, str, bytes_num);
|
||||
}
|
||||
|
||||
void *MEM_guarded_calloc_arrayN_aligned(const size_t len,
|
||||
const size_t size,
|
||||
const size_t alignment,
|
||||
const char *str)
|
||||
{
|
||||
size_t bytes_num;
|
||||
/* There is no lower level #calloc with an alignment parameter, so we have to fallback to using
|
||||
* #memset unfortunately. */
|
||||
void *ptr = MEM_mallocN_aligned(bytes_num, alignment, str);
|
||||
void *ptr = mem_guarded_malloc_arrayN_aligned(len, size, alignment, str, bytes_num);
|
||||
if (!ptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -135,6 +135,11 @@ void *MEM_lockfree_mallocN_aligned(size_t len,
|
||||
const char *str,
|
||||
mem_guarded::internal::AllocationType allocation_type)
|
||||
ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_ALLOC_SIZE(1) ATTR_NONNULL(3);
|
||||
void *MEM_lockfree_malloc_arrayN_aligned(size_t len,
|
||||
size_t size,
|
||||
size_t alignment,
|
||||
const char *str) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
|
||||
ATTR_ALLOC_SIZE(1, 2) ATTR_NONNULL(4);
|
||||
void *MEM_lockfree_calloc_arrayN_aligned(size_t len,
|
||||
size_t size,
|
||||
size_t alignment,
|
||||
@@ -188,6 +193,8 @@ void *MEM_guarded_mallocN_aligned(size_t len,
|
||||
const char *str,
|
||||
mem_guarded::internal::AllocationType allocation_type)
|
||||
ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_ALLOC_SIZE(1) ATTR_NONNULL(3);
|
||||
void *MEM_guarded_malloc_arrayN_aligned(size_t len, size_t size, size_t alignment, const char *str)
|
||||
ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_ALLOC_SIZE(1, 2) ATTR_NONNULL(4);
|
||||
void *MEM_guarded_calloc_arrayN_aligned(size_t len, size_t size, size_t alignment, const char *str)
|
||||
ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_ALLOC_SIZE(1, 2) ATTR_NONNULL(4);
|
||||
void MEM_guarded_printmemlist_pydict(void);
|
||||
|
||||
@@ -456,13 +456,13 @@ void *MEM_lockfree_mallocN_aligned(size_t len,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void *MEM_lockfree_calloc_arrayN_aligned(const size_t len,
|
||||
const size_t size,
|
||||
const size_t alignment,
|
||||
const char *str)
|
||||
static void *mem_lockfree_malloc_arrayN_aligned(const size_t len,
|
||||
const size_t size,
|
||||
const size_t alignment,
|
||||
const char *str,
|
||||
size_t &r_bytes_num)
|
||||
{
|
||||
size_t bytes_num;
|
||||
if (UNLIKELY(!MEM_size_safe_multiply(len, size, &bytes_num))) {
|
||||
if (UNLIKELY(!MEM_size_safe_multiply(len, size, &r_bytes_num))) {
|
||||
print_error(
|
||||
"Calloc array aborted due to integer overflow: "
|
||||
"len=" SIZET_FORMAT "x" SIZET_FORMAT " in %s, total " SIZET_FORMAT "\n",
|
||||
@@ -474,11 +474,30 @@ void *MEM_lockfree_calloc_arrayN_aligned(const size_t len,
|
||||
return nullptr;
|
||||
}
|
||||
if (alignment <= MEM_MIN_CPP_ALIGNMENT) {
|
||||
return MEM_callocN(bytes_num, str);
|
||||
return MEM_mallocN(r_bytes_num, str);
|
||||
}
|
||||
void *ptr = MEM_mallocN_aligned(r_bytes_num, alignment, str);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *MEM_lockfree_malloc_arrayN_aligned(const size_t len,
|
||||
const size_t size,
|
||||
const size_t alignment,
|
||||
const char *str)
|
||||
{
|
||||
size_t bytes_num;
|
||||
return mem_lockfree_malloc_arrayN_aligned(len, size, alignment, str, bytes_num);
|
||||
}
|
||||
|
||||
void *MEM_lockfree_calloc_arrayN_aligned(const size_t len,
|
||||
const size_t size,
|
||||
const size_t alignment,
|
||||
const char *str)
|
||||
{
|
||||
size_t bytes_num;
|
||||
/* There is no lower level #calloc with an alignment parameter, so we have to fallback to using
|
||||
* #memset unfortunately. */
|
||||
void *ptr = MEM_mallocN_aligned(bytes_num, alignment, str);
|
||||
void *ptr = mem_lockfree_malloc_arrayN_aligned(len, size, alignment, str, bytes_num);
|
||||
if (!ptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -23,13 +23,14 @@
|
||||
{ \
|
||||
if (what) { \
|
||||
((type*)what)->~type(); \
|
||||
MEM_freeN(what); \
|
||||
MEM_freeN(const_cast<void*>(static_cast<const void*>(what))); \
|
||||
} \
|
||||
} \
|
||||
(void)0
|
||||
# define LIBMV_STRUCT_NEW(type, count) \
|
||||
(type*)MEM_mallocN(sizeof(type) * count, __func__)
|
||||
# define LIBMV_STRUCT_DELETE(what) MEM_freeN(what)
|
||||
# define LIBMV_STRUCT_DELETE(what) \
|
||||
MEM_freeN(const_cast<void*>(static_cast<const void*>(what)))
|
||||
#else
|
||||
// Need this to keep libmv-capi potentially standalone.
|
||||
# if defined __GNUC__ || defined __sun
|
||||
|
||||
@@ -56,7 +56,7 @@ template<typename _Tp> struct MEM_Allocator {
|
||||
// __p is not permitted to be a null pointer.
|
||||
void deallocate(pointer __p, size_type /*unused*/)
|
||||
{
|
||||
MEM_freeN(__p);
|
||||
MEM_freeN(static_cast<void *>(__p));
|
||||
}
|
||||
|
||||
size_type max_size() const noexcept
|
||||
|
||||
@@ -526,7 +526,7 @@ OCIO_PackedImageDesc *FallbackImpl::createOCIO_PackedImageDesc(float *data,
|
||||
|
||||
void FallbackImpl::OCIO_PackedImageDescRelease(OCIO_PackedImageDesc *id)
|
||||
{
|
||||
MEM_freeN(id);
|
||||
MEM_freeN(reinterpret_cast<OCIO_PackedImageDescription *>(id));
|
||||
}
|
||||
|
||||
const char *FallbackImpl::getVersionString()
|
||||
|
||||
@@ -266,7 +266,12 @@ void BKE_view_layer_free_ex(ViewLayer *view_layer, const bool do_id_user)
|
||||
BLI_freelistN(&view_layer->lightgroups);
|
||||
view_layer->active_lightgroup = nullptr;
|
||||
|
||||
MEM_SAFE_FREE(view_layer->stats);
|
||||
/* Cannot use MEM_SAFE_FREE, as #SceneStats type is only forward-declared in `DNA_layer_types.h`
|
||||
*/
|
||||
if (view_layer->stats) {
|
||||
MEM_freeN(static_cast<void *>(view_layer->stats));
|
||||
view_layer->stats = nullptr;
|
||||
}
|
||||
|
||||
BKE_freestyle_config_free(&view_layer->freestyle_config, do_id_user);
|
||||
|
||||
|
||||
@@ -170,7 +170,7 @@ void BKE_main_destroy(Main &bmain)
|
||||
BKE_main_clear(bmain);
|
||||
|
||||
BLI_spin_end(reinterpret_cast<SpinLock *>(bmain.lock));
|
||||
MEM_freeN(bmain.lock);
|
||||
MEM_freeN(static_cast<void *>(bmain.lock));
|
||||
bmain.lock = nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -195,8 +195,7 @@ void BKE_main_namemap_destroy(UniqueName_Map **r_name_map)
|
||||
printf(
|
||||
"NameMap memory usage: sets %.1fKB, maps %.1fKB\n", size_sets / 1024.0, size_maps / 1024.0);
|
||||
#endif
|
||||
MEM_delete<UniqueName_Map>(*r_name_map);
|
||||
*r_name_map = nullptr;
|
||||
MEM_SAFE_DELETE(*r_name_map);
|
||||
}
|
||||
|
||||
void BKE_main_namemap_clear(Main *bmain)
|
||||
|
||||
@@ -1116,7 +1116,7 @@ void multires_modifier_update_mdisps(DerivedMesh *dm, Scene *scene)
|
||||
}
|
||||
|
||||
/* lower level dm no longer needed at this point */
|
||||
MEM_freeN(diffGrid);
|
||||
MEM_freeN(static_cast<void *>(diffGrid));
|
||||
lowdm->release(lowdm);
|
||||
|
||||
/* subsurf higher levels again with difference of coordinates */
|
||||
@@ -1130,7 +1130,7 @@ void multires_modifier_update_mdisps(DerivedMesh *dm, Scene *scene)
|
||||
/* free */
|
||||
highdm->release(highdm);
|
||||
for (i = 0; i < numGrids; i++) {
|
||||
MEM_freeN(subGridData[i]);
|
||||
MEM_freeN(static_cast<void *>(subGridData[i]));
|
||||
}
|
||||
MEM_freeN(subGridData);
|
||||
}
|
||||
@@ -1282,7 +1282,7 @@ DerivedMesh *multires_make_derived_from_derived(
|
||||
}
|
||||
|
||||
for (i = 0; i < numGrids; i++) {
|
||||
MEM_freeN(subGridData[i]);
|
||||
MEM_freeN(static_cast<void *>(subGridData[i]));
|
||||
}
|
||||
MEM_freeN(subGridData);
|
||||
|
||||
|
||||
@@ -78,7 +78,12 @@ static void screen_free_data(ID *id)
|
||||
BKE_previewimg_free(&screen->preview);
|
||||
|
||||
/* Region and timer are freed by the window manager. */
|
||||
MEM_SAFE_FREE(screen->tool_tip);
|
||||
/* Cannot use MEM_SAFE_FREE, as #wmTooltipState type is only defined in `WM_types.hh`, which is
|
||||
* currently not included here. */
|
||||
if (screen->tool_tip) {
|
||||
MEM_freeN(static_cast<void *>(screen->tool_tip));
|
||||
screen->tool_tip = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_screen_foreach_id_screen_area(LibraryForeachIDData *data, ScrArea *area)
|
||||
|
||||
@@ -172,14 +172,13 @@ void BLI_bitmap_randomize(BLI_bitmap *bitmap, uint bits_num, uint seed)
|
||||
/* ********* for threaded random ************** */
|
||||
|
||||
struct RNG_THREAD_ARRAY {
|
||||
RNG rng_tab[BLENDER_MAX_THREADS];
|
||||
std::array<RNG, BLENDER_MAX_THREADS> rng_tab;
|
||||
};
|
||||
|
||||
RNG_THREAD_ARRAY *BLI_rng_threaded_new()
|
||||
{
|
||||
uint i;
|
||||
RNG_THREAD_ARRAY *rngarr = (RNG_THREAD_ARRAY *)MEM_mallocN(sizeof(RNG_THREAD_ARRAY),
|
||||
"random_array");
|
||||
RNG_THREAD_ARRAY *rngarr = MEM_new<RNG_THREAD_ARRAY>("random_array");
|
||||
|
||||
for (i = 0; i < BLENDER_MAX_THREADS; i++) {
|
||||
BLI_rng_srandom(&rngarr->rng_tab[i], uint(clock()));
|
||||
@@ -190,12 +189,12 @@ RNG_THREAD_ARRAY *BLI_rng_threaded_new()
|
||||
|
||||
void BLI_rng_threaded_free(RNG_THREAD_ARRAY *rngarr)
|
||||
{
|
||||
MEM_freeN(rngarr);
|
||||
MEM_delete(rngarr);
|
||||
}
|
||||
|
||||
int BLI_rng_thread_rand(RNG_THREAD_ARRAY *rngarr, int thread)
|
||||
{
|
||||
return BLI_rng_get_int(&rngarr->rng_tab[thread]);
|
||||
return BLI_rng_get_int(&rngarr->rng_tab[size_t(thread)]);
|
||||
}
|
||||
|
||||
/* ********* Low-discrepancy sequences ************** */
|
||||
|
||||
@@ -68,7 +68,7 @@ struct TimeSourceNode;
|
||||
class DepsgraphNodeBuilder : public DepsgraphBuilder {
|
||||
public:
|
||||
DepsgraphNodeBuilder(Main *bmain, Depsgraph *graph, DepsgraphBuilderCache *cache);
|
||||
~DepsgraphNodeBuilder() override;
|
||||
~DepsgraphNodeBuilder();
|
||||
|
||||
/* For given original ID get ID which is created by copy-on-evaluation system. */
|
||||
ID *get_cow_id(const ID *id_orig) const;
|
||||
|
||||
@@ -290,7 +290,7 @@ class UniformArrayBuffer : public detail::UniformCommon<T, len, false> {
|
||||
}
|
||||
~UniformArrayBuffer()
|
||||
{
|
||||
MEM_freeN(this->data_);
|
||||
MEM_freeN(static_cast<void *>(this->data_));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -337,7 +337,9 @@ class StorageArrayBuffer : public detail::StorageCommon<T, len, device_only> {
|
||||
}
|
||||
~StorageArrayBuffer()
|
||||
{
|
||||
MEM_freeN(this->data_);
|
||||
/* NOTE: T is not always trivial (e.g. can be #blender::eevee::VelocityIndex), so cannot use
|
||||
* `MEM_freeN` directly on it, without casting it to `void *`. */
|
||||
MEM_freeN(static_cast<void *>(this->data_));
|
||||
}
|
||||
|
||||
/* Resize to \a new_size elements. */
|
||||
@@ -348,7 +350,7 @@ class StorageArrayBuffer : public detail::StorageCommon<T, len, device_only> {
|
||||
/* Manual realloc since MEM_reallocN_aligned does not exists. */
|
||||
T *new_data_ = (T *)MEM_mallocN_aligned(new_size * sizeof(T), 16, this->name_);
|
||||
memcpy(new_data_, this->data_, min_uu(this->len_, new_size) * sizeof(T));
|
||||
MEM_freeN(this->data_);
|
||||
MEM_freeN(static_cast<void *>(this->data_));
|
||||
this->data_ = new_data_;
|
||||
GPU_storagebuf_free(this->ssbo_);
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ class FileListWrapper {
|
||||
static void filelist_free_fn(FileList *list)
|
||||
{
|
||||
filelist_free(list);
|
||||
MEM_freeN(list);
|
||||
MEM_freeN(static_cast<void *>(list));
|
||||
}
|
||||
|
||||
std::unique_ptr<FileList, decltype(&filelist_free_fn)> file_list_;
|
||||
|
||||
@@ -1290,7 +1290,11 @@ static void gizmo_cage2d_exit(bContext *C, wmGizmo *gz, const bool cancel)
|
||||
{
|
||||
RectTransformInteraction *data = static_cast<RectTransformInteraction *>(gz->interaction_data);
|
||||
|
||||
MEM_SAFE_FREE(data->dial);
|
||||
/* Cannot use MEM_SAFE_FREE, as #Dial type is only forward-declared in `BLI_dial_2d.h` */
|
||||
if (data->dial) {
|
||||
MEM_freeN(static_cast<void *>(data->dial));
|
||||
data->dial = nullptr;
|
||||
}
|
||||
|
||||
if (!cancel) {
|
||||
return;
|
||||
|
||||
@@ -1073,7 +1073,7 @@ static void annotation_free_stroke(bGPDframe *gpf, bGPDstroke *gps)
|
||||
|
||||
if (gps->dvert) {
|
||||
BKE_gpencil_free_stroke_weights(gps);
|
||||
MEM_freeN(gps->dvert);
|
||||
MEM_freeN(static_cast<void *>(gps->dvert));
|
||||
}
|
||||
|
||||
if (gps->triangles) {
|
||||
|
||||
@@ -71,7 +71,7 @@ void region_reset(ARegion ®ion, const RegionViewData &data)
|
||||
region.winrct = data.winrct;
|
||||
|
||||
ED_view3d_mats_rv3d_restore(&rv3d, data.rv3d_store);
|
||||
MEM_freeN(data.rv3d_store);
|
||||
MEM_freeN(static_cast<void *>(data.rv3d_store));
|
||||
}
|
||||
|
||||
GPUOffScreen *image_render_begin(const int2 &win_size)
|
||||
|
||||
@@ -3905,7 +3905,11 @@ namespace blender::ed::sculpt_paint {
|
||||
|
||||
StrokeCache::~StrokeCache()
|
||||
{
|
||||
MEM_SAFE_FREE(this->dial);
|
||||
/* Cannot use MEM_SAFE_FREE, as #Dial type is only forward-declared in `BLI_dial_2d.h` */
|
||||
if (this->dial) {
|
||||
MEM_freeN(static_cast<void *>(this->dial));
|
||||
this->dial = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace blender::ed::sculpt_paint
|
||||
|
||||
@@ -1329,7 +1329,7 @@ void ED_fileselect_exit(wmWindowManager *wm, SpaceFile *sfile)
|
||||
if (sfile->files) {
|
||||
ED_fileselect_clear(wm, sfile);
|
||||
filelist_free(sfile->files);
|
||||
MEM_freeN(sfile->files);
|
||||
MEM_freeN(static_cast<void *>(sfile->files));
|
||||
sfile->files = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ static void file_free(SpaceLink *sl)
|
||||
/* XXX would need to do thumbnails_stop here, but no context available */
|
||||
filelist_freelib(sfile->files);
|
||||
filelist_free(sfile->files);
|
||||
MEM_freeN(sfile->files);
|
||||
MEM_freeN(static_cast<void *>(sfile->files));
|
||||
sfile->files = nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -277,7 +277,12 @@ static void view3d_free(SpaceLink *sl)
|
||||
MEM_freeN(vd->localvd);
|
||||
}
|
||||
|
||||
MEM_SAFE_FREE(vd->runtime.local_stats);
|
||||
/* Cannot use MEM_SAFE_FREE, as #SceneStats type is only forward-declared in `DNA_layer_types.h`
|
||||
*/
|
||||
if (vd->runtime.local_stats) {
|
||||
MEM_freeN(static_cast<void *>(vd->runtime.local_stats));
|
||||
vd->runtime.local_stats = nullptr;
|
||||
}
|
||||
|
||||
if (vd->runtime.properties_storage_free) {
|
||||
vd->runtime.properties_storage_free(vd->runtime.properties_storage);
|
||||
@@ -299,7 +304,12 @@ static void view3d_exit(wmWindowManager * /*wm*/, ScrArea *area)
|
||||
{
|
||||
BLI_assert(area->spacetype == SPACE_VIEW3D);
|
||||
View3D *v3d = static_cast<View3D *>(area->spacedata.first);
|
||||
MEM_SAFE_FREE(v3d->runtime.local_stats);
|
||||
/* Cannot use MEM_SAFE_FREE, as #SceneStats type is only forward-declared in `DNA_layer_types.h`
|
||||
*/
|
||||
if (v3d->runtime.local_stats) {
|
||||
MEM_freeN(static_cast<void *>(v3d->runtime.local_stats));
|
||||
v3d->runtime.local_stats = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static SpaceLink *view3d_duplicate(SpaceLink *sl)
|
||||
@@ -1048,7 +1058,7 @@ static void view3d_main_region_free(ARegion *region)
|
||||
}
|
||||
|
||||
if (rv3d->sms) {
|
||||
MEM_freeN(rv3d->sms);
|
||||
MEM_freeN(static_cast<void *>(rv3d->sms));
|
||||
}
|
||||
|
||||
MEM_freeN(rv3d);
|
||||
@@ -2006,7 +2016,12 @@ static void space_view3d_listener(const wmSpaceTypeListenerParams *params)
|
||||
static void space_view3d_refresh(const bContext *C, ScrArea *area)
|
||||
{
|
||||
View3D *v3d = (View3D *)area->spacedata.first;
|
||||
MEM_SAFE_FREE(v3d->runtime.local_stats);
|
||||
/* Cannot use MEM_SAFE_FREE, as #SceneStats type is only forward-declared in `DNA_layer_types.h`
|
||||
*/
|
||||
if (v3d->runtime.local_stats) {
|
||||
MEM_freeN(static_cast<void *>(v3d->runtime.local_stats));
|
||||
v3d->runtime.local_stats = nullptr;
|
||||
}
|
||||
|
||||
if (v3d->localvd && v3d->localvd->runtime.flag & V3D_RUNTIME_LOCAL_MAYBE_EMPTY) {
|
||||
ED_localview_exit_if_empty(CTX_data_ensure_evaluated_depsgraph(C),
|
||||
|
||||
@@ -385,7 +385,11 @@ void ViewOpsData::end_navigation(bContext *C)
|
||||
WM_event_timer_remove(CTX_wm_manager(C), this->timer->win, this->timer);
|
||||
}
|
||||
|
||||
MEM_SAFE_FREE(this->init.dial);
|
||||
/* Cannot use MEM_SAFE_FREE, as #Dial type is only forward-declared in `BLI_dial_2d.h` */
|
||||
if (this->init.dial) {
|
||||
MEM_freeN(static_cast<void *>(this->init.dial));
|
||||
this->init.dial = nullptr;
|
||||
}
|
||||
|
||||
/* Need to redraw because drawing code uses RV3D_NAVIGATING to draw
|
||||
* faster while navigation operator runs. */
|
||||
|
||||
@@ -985,7 +985,12 @@ static bool view3d_localview_exit(const Depsgraph *depsgraph,
|
||||
|
||||
MEM_freeN(v3d->localvd);
|
||||
v3d->localvd = nullptr;
|
||||
MEM_SAFE_FREE(v3d->runtime.local_stats);
|
||||
/* Cannot use MEM_SAFE_FREE, as #SceneStats type is only forward-declared in `DNA_layer_types.h`
|
||||
*/
|
||||
if (v3d->runtime.local_stats) {
|
||||
MEM_freeN(static_cast<void *>(v3d->runtime.local_stats));
|
||||
v3d->runtime.local_stats = nullptr;
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
|
||||
if (region->regiontype == RGN_TYPE_WINDOW) {
|
||||
|
||||
@@ -3507,7 +3507,7 @@ static int uv_from_view_exec(bContext *C, wmOperator *op)
|
||||
changed = true;
|
||||
}
|
||||
|
||||
MEM_freeN(uci);
|
||||
MEM_freeN(static_cast<void *>(uci));
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -269,7 +269,8 @@ static void rna_Main_materials_gpencil_remove(Main * /*bmain*/, PointerRNA *id_p
|
||||
ID *id = static_cast<ID *>(id_ptr->data);
|
||||
Material *ma = (Material *)id;
|
||||
if (ma->gp_style) {
|
||||
MEM_SAFE_FREE(ma->gp_style);
|
||||
MEM_freeN(ma->gp_style);
|
||||
ma->gp_style = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -159,7 +159,7 @@ void WM_gizmo_free(wmGizmo *gz)
|
||||
/* Explicit calling of the destructor is needed here because allocation still happens 'the C
|
||||
* way', see FIXME note in #wm_gizmo_create. */
|
||||
gz->~wmGizmo();
|
||||
MEM_freeN(gz);
|
||||
MEM_freeN(static_cast<void *>(gz));
|
||||
}
|
||||
|
||||
void WM_gizmo_unlink(ListBase *gizmolist, wmGizmoMap *gzmap, wmGizmo *gz, bContext *C)
|
||||
|
||||
@@ -3208,7 +3208,11 @@ static void radial_control_cancel(bContext *C, wmOperator *op)
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
ScrArea *area = CTX_wm_area(C);
|
||||
|
||||
MEM_SAFE_FREE(rc->dial);
|
||||
/* Cannot use MEM_SAFE_FREE, as #Dial type is only forward-declared in `BLI_dial_2d.h` */
|
||||
if (rc->dial) {
|
||||
MEM_freeN(static_cast<void *>(rc->dial));
|
||||
rc->dial = nullptr;
|
||||
}
|
||||
|
||||
ED_area_status_text(area, nullptr);
|
||||
|
||||
@@ -3401,7 +3405,11 @@ static int radial_control_modal(bContext *C, wmOperator *op, const wmEvent *even
|
||||
if (event->val == KM_RELEASE) {
|
||||
rc->slow_mode = false;
|
||||
handled = true;
|
||||
MEM_SAFE_FREE(rc->dial);
|
||||
/* Cannot use MEM_SAFE_FREE, as #Dial type is only forward-declared in `BLI_dial_2d.h` */
|
||||
if (rc->dial) {
|
||||
MEM_freeN(static_cast<void *>(rc->dial));
|
||||
rc->dial = nullptr;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user