From 48e26c3afeca471ee8f9a281fe8c7ebe04015cb1 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 20 Feb 2025 10:37:10 +0100 Subject: [PATCH] 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 --- intern/cycles/util/guarded_allocator.h | 2 +- intern/cycles/util/stack_allocator.h | 2 +- intern/guardedalloc/MEM_guardedalloc.h | 49 +++++++++++++++++-- intern/guardedalloc/intern/mallocn.cc | 6 +++ .../intern/mallocn_guarded_impl.cc | 34 ++++++++++--- intern/guardedalloc/intern/mallocn_intern.hh | 7 +++ .../intern/mallocn_lockfree_impl.cc | 35 ++++++++++--- intern/libmv/intern/utildefines.h | 5 +- intern/memutil/MEM_Allocator.h | 2 +- intern/opencolorio/fallback_impl.cc | 2 +- source/blender/blenkernel/intern/layer.cc | 7 ++- source/blender/blenkernel/intern/main.cc | 2 +- .../blender/blenkernel/intern/main_namemap.cc | 3 +- source/blender/blenkernel/intern/multires.cc | 6 +-- source/blender/blenkernel/intern/screen.cc | 7 ++- source/blender/blenlib/intern/rand.cc | 9 ++-- .../intern/builder/deg_builder_nodes.h | 2 +- source/blender/draw/intern/DRW_gpu_wrapper.hh | 8 +-- .../editors/asset/intern/asset_list.cc | 2 +- .../gizmo_library/gizmo_types/cage2d_gizmo.cc | 6 ++- .../editors/gpencil_legacy/annotate_paint.cc | 2 +- .../intern/grease_pencil_image_render.cc | 2 +- source/blender/editors/sculpt_paint/sculpt.cc | 6 ++- source/blender/editors/space_file/filesel.cc | 2 +- .../blender/editors/space_file/space_file.cc | 2 +- .../editors/space_view3d/space_view3d.cc | 23 +++++++-- .../editors/space_view3d/view3d_navigate.cc | 6 ++- .../editors/space_view3d/view3d_view.cc | 7 ++- .../editors/uvedit/uvedit_unwrap_ops.cc | 2 +- .../blender/makesrna/intern/rna_main_api.cc | 3 +- .../windowmanager/gizmo/intern/wm_gizmo.cc | 2 +- .../windowmanager/intern/wm_operators.cc | 12 ++++- 32 files changed, 203 insertions(+), 62 deletions(-) diff --git a/intern/cycles/util/guarded_allocator.h b/intern/cycles/util/guarded_allocator.h index cb20211a3d5..57cf45fd418 100644 --- a/intern/cycles/util/guarded_allocator.h +++ b/intern/cycles/util/guarded_allocator.h @@ -61,7 +61,7 @@ template class GuardedAllocator { util_guarded_mem_free(n * sizeof(T)); if (p != nullptr) { #ifdef WITH_BLENDER_GUARDEDALLOC - MEM_freeN(p); + MEM_freeN(const_cast(static_cast(p))); #else free(p); #endif diff --git a/intern/cycles/util/stack_allocator.h b/intern/cycles/util/stack_allocator.h index 57f64417542..68d80ec49e5 100644 --- a/intern/cycles/util/stack_allocator.h +++ b/intern/cycles/util/stack_allocator.h @@ -69,7 +69,7 @@ template 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(p)); #else free(p); #endif diff --git a/intern/guardedalloc/MEM_guardedalloc.h b/intern/guardedalloc/MEM_guardedalloc.h index 83d2d33ace8..9531c71ff8f 100644 --- a/intern/guardedalloc/MEM_guardedalloc.h +++ b/intern/guardedalloc/MEM_guardedalloc.h @@ -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>); \ - void **_v = (void **)&(v); \ - if (*_v) { \ - MEM_freeN(*_v); \ - *_v = NULL; \ + if (v) { \ + MEM_freeN>>(v); \ + (v) = nullptr; \ } \ } while (0) #else @@ -334,6 +342,18 @@ template 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 inline T *MEM_cnew(const char *allocation_name, const T &ot return new_object; } +template inline void MEM_freeN(T *ptr) +{ + if constexpr (std::is_void_v) { + mem_guarded::internal::mem_freeN_ex(const_cast(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, "For non-trivial types, MEM_delete must be used."); +# endif + mem_guarded::internal::mem_freeN_ex(const_cast(static_cast(ptr)), + mem_guarded::internal::AllocationType::ALLOC_FREE); + } +} + /** Allocation functions (for C++ only). */ # define MEM_CXX_CLASS_ALLOC_FUNCS(_id) \ public: \ diff --git a/intern/guardedalloc/intern/mallocn.cc b/intern/guardedalloc/intern/mallocn.cc index 193f531e683..7080ac070e1 100644 --- a/intern/guardedalloc/intern/mallocn.cc +++ b/intern/guardedalloc/intern/mallocn.cc @@ -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; diff --git a/intern/guardedalloc/intern/mallocn_guarded_impl.cc b/intern/guardedalloc/intern/mallocn_guarded_impl.cc index 90e6010a4f9..e888b50987f 100644 --- a/intern/guardedalloc/intern/mallocn_guarded_impl.cc +++ b/intern/guardedalloc/intern/mallocn_guarded_impl.cc @@ -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; } diff --git a/intern/guardedalloc/intern/mallocn_intern.hh b/intern/guardedalloc/intern/mallocn_intern.hh index 3533cc1b236..60ea69c55fb 100644 --- a/intern/guardedalloc/intern/mallocn_intern.hh +++ b/intern/guardedalloc/intern/mallocn_intern.hh @@ -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); diff --git a/intern/guardedalloc/intern/mallocn_lockfree_impl.cc b/intern/guardedalloc/intern/mallocn_lockfree_impl.cc index 30c4c57c5bf..096924f93bf 100644 --- a/intern/guardedalloc/intern/mallocn_lockfree_impl.cc +++ b/intern/guardedalloc/intern/mallocn_lockfree_impl.cc @@ -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; } diff --git a/intern/libmv/intern/utildefines.h b/intern/libmv/intern/utildefines.h index a845b935189..c0ef0a526b8 100644 --- a/intern/libmv/intern/utildefines.h +++ b/intern/libmv/intern/utildefines.h @@ -23,13 +23,14 @@ { \ if (what) { \ ((type*)what)->~type(); \ - MEM_freeN(what); \ + MEM_freeN(const_cast(static_cast(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(static_cast(what))) #else // Need this to keep libmv-capi potentially standalone. # if defined __GNUC__ || defined __sun diff --git a/intern/memutil/MEM_Allocator.h b/intern/memutil/MEM_Allocator.h index bff3c3f7d40..a9475dcba01 100644 --- a/intern/memutil/MEM_Allocator.h +++ b/intern/memutil/MEM_Allocator.h @@ -56,7 +56,7 @@ template 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(__p)); } size_type max_size() const noexcept diff --git a/intern/opencolorio/fallback_impl.cc b/intern/opencolorio/fallback_impl.cc index 9f8afd231e4..9fe68ff824e 100644 --- a/intern/opencolorio/fallback_impl.cc +++ b/intern/opencolorio/fallback_impl.cc @@ -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(id)); } const char *FallbackImpl::getVersionString() diff --git a/source/blender/blenkernel/intern/layer.cc b/source/blender/blenkernel/intern/layer.cc index 47752c2df71..c1d784e8f16 100644 --- a/source/blender/blenkernel/intern/layer.cc +++ b/source/blender/blenkernel/intern/layer.cc @@ -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(view_layer->stats)); + view_layer->stats = nullptr; + } BKE_freestyle_config_free(&view_layer->freestyle_config, do_id_user); diff --git a/source/blender/blenkernel/intern/main.cc b/source/blender/blenkernel/intern/main.cc index 7728db1c9a0..375aa68b1a1 100644 --- a/source/blender/blenkernel/intern/main.cc +++ b/source/blender/blenkernel/intern/main.cc @@ -170,7 +170,7 @@ void BKE_main_destroy(Main &bmain) BKE_main_clear(bmain); BLI_spin_end(reinterpret_cast(bmain.lock)); - MEM_freeN(bmain.lock); + MEM_freeN(static_cast(bmain.lock)); bmain.lock = nullptr; } diff --git a/source/blender/blenkernel/intern/main_namemap.cc b/source/blender/blenkernel/intern/main_namemap.cc index 0a3952d8eba..15e31588c26 100644 --- a/source/blender/blenkernel/intern/main_namemap.cc +++ b/source/blender/blenkernel/intern/main_namemap.cc @@ -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(*r_name_map); - *r_name_map = nullptr; + MEM_SAFE_DELETE(*r_name_map); } void BKE_main_namemap_clear(Main *bmain) diff --git a/source/blender/blenkernel/intern/multires.cc b/source/blender/blenkernel/intern/multires.cc index 10ae7582866..ffaf8d08b94 100644 --- a/source/blender/blenkernel/intern/multires.cc +++ b/source/blender/blenkernel/intern/multires.cc @@ -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(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(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(subGridData[i])); } MEM_freeN(subGridData); diff --git a/source/blender/blenkernel/intern/screen.cc b/source/blender/blenkernel/intern/screen.cc index a2f0a982a54..891ac072154 100644 --- a/source/blender/blenkernel/intern/screen.cc +++ b/source/blender/blenkernel/intern/screen.cc @@ -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(screen->tool_tip)); + screen->tool_tip = nullptr; + } } void BKE_screen_foreach_id_screen_area(LibraryForeachIDData *data, ScrArea *area) diff --git a/source/blender/blenlib/intern/rand.cc b/source/blender/blenlib/intern/rand.cc index 9f9bb4d23c0..65355ca091f 100644 --- a/source/blender/blenlib/intern/rand.cc +++ b/source/blender/blenlib/intern/rand.cc @@ -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_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("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 ************** */ diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h index 66955981fdd..2769988891a 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h @@ -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; diff --git a/source/blender/draw/intern/DRW_gpu_wrapper.hh b/source/blender/draw/intern/DRW_gpu_wrapper.hh index 7c6f7933f47..b871b6336cf 100644 --- a/source/blender/draw/intern/DRW_gpu_wrapper.hh +++ b/source/blender/draw/intern/DRW_gpu_wrapper.hh @@ -290,7 +290,7 @@ class UniformArrayBuffer : public detail::UniformCommon { } ~UniformArrayBuffer() { - MEM_freeN(this->data_); + MEM_freeN(static_cast(this->data_)); } }; @@ -337,7 +337,9 @@ class StorageArrayBuffer : public detail::StorageCommon { } ~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(this->data_)); } /* Resize to \a new_size elements. */ @@ -348,7 +350,7 @@ class StorageArrayBuffer : public detail::StorageCommon { /* 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(this->data_)); this->data_ = new_data_; GPU_storagebuf_free(this->ssbo_); diff --git a/source/blender/editors/asset/intern/asset_list.cc b/source/blender/editors/asset/intern/asset_list.cc index 67970c165d6..9f85df6c425 100644 --- a/source/blender/editors/asset/intern/asset_list.cc +++ b/source/blender/editors/asset/intern/asset_list.cc @@ -57,7 +57,7 @@ class FileListWrapper { static void filelist_free_fn(FileList *list) { filelist_free(list); - MEM_freeN(list); + MEM_freeN(static_cast(list)); } std::unique_ptr file_list_; diff --git a/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.cc b/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.cc index d18778993d4..a3471e3a179 100644 --- a/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.cc +++ b/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.cc @@ -1290,7 +1290,11 @@ static void gizmo_cage2d_exit(bContext *C, wmGizmo *gz, const bool cancel) { RectTransformInteraction *data = static_cast(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(data->dial)); + data->dial = nullptr; + } if (!cancel) { return; diff --git a/source/blender/editors/gpencil_legacy/annotate_paint.cc b/source/blender/editors/gpencil_legacy/annotate_paint.cc index 74edffb1772..ab02219a7af 100644 --- a/source/blender/editors/gpencil_legacy/annotate_paint.cc +++ b/source/blender/editors/gpencil_legacy/annotate_paint.cc @@ -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(gps->dvert)); } if (gps->triangles) { diff --git a/source/blender/editors/grease_pencil/intern/grease_pencil_image_render.cc b/source/blender/editors/grease_pencil/intern/grease_pencil_image_render.cc index 1b786578df8..9c3f6f21fe3 100644 --- a/source/blender/editors/grease_pencil/intern/grease_pencil_image_render.cc +++ b/source/blender/editors/grease_pencil/intern/grease_pencil_image_render.cc @@ -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(data.rv3d_store)); } GPUOffScreen *image_render_begin(const int2 &win_size) diff --git a/source/blender/editors/sculpt_paint/sculpt.cc b/source/blender/editors/sculpt_paint/sculpt.cc index ad579620534..dbc1957dc2e 100644 --- a/source/blender/editors/sculpt_paint/sculpt.cc +++ b/source/blender/editors/sculpt_paint/sculpt.cc @@ -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(this->dial)); + this->dial = nullptr; + } } } // namespace blender::ed::sculpt_paint diff --git a/source/blender/editors/space_file/filesel.cc b/source/blender/editors/space_file/filesel.cc index 0969751d937..bc507775e82 100644 --- a/source/blender/editors/space_file/filesel.cc +++ b/source/blender/editors/space_file/filesel.cc @@ -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(sfile->files)); sfile->files = nullptr; } } diff --git a/source/blender/editors/space_file/space_file.cc b/source/blender/editors/space_file/space_file.cc index e6df554b896..bc84e7d9aed 100644 --- a/source/blender/editors/space_file/space_file.cc +++ b/source/blender/editors/space_file/space_file.cc @@ -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(sfile->files)); sfile->files = nullptr; } diff --git a/source/blender/editors/space_view3d/space_view3d.cc b/source/blender/editors/space_view3d/space_view3d.cc index 7dc390fc4b1..94fdcd72e94 100644 --- a/source/blender/editors/space_view3d/space_view3d.cc +++ b/source/blender/editors/space_view3d/space_view3d.cc @@ -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(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(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(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(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(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), diff --git a/source/blender/editors/space_view3d/view3d_navigate.cc b/source/blender/editors/space_view3d/view3d_navigate.cc index 241decb9fa3..e2295831c71 100644 --- a/source/blender/editors/space_view3d/view3d_navigate.cc +++ b/source/blender/editors/space_view3d/view3d_navigate.cc @@ -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(this->init.dial)); + this->init.dial = nullptr; + } /* Need to redraw because drawing code uses RV3D_NAVIGATING to draw * faster while navigation operator runs. */ diff --git a/source/blender/editors/space_view3d/view3d_view.cc b/source/blender/editors/space_view3d/view3d_view.cc index 59c06dc1bdc..146f53f8b2c 100644 --- a/source/blender/editors/space_view3d/view3d_view.cc +++ b/source/blender/editors/space_view3d/view3d_view.cc @@ -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(v3d->runtime.local_stats)); + v3d->runtime.local_stats = nullptr; + } LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { if (region->regiontype == RGN_TYPE_WINDOW) { diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.cc b/source/blender/editors/uvedit/uvedit_unwrap_ops.cc index 2e942c11694..1835947e5c7 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.cc +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.cc @@ -3507,7 +3507,7 @@ static int uv_from_view_exec(bContext *C, wmOperator *op) changed = true; } - MEM_freeN(uci); + MEM_freeN(static_cast(uci)); } } else { diff --git a/source/blender/makesrna/intern/rna_main_api.cc b/source/blender/makesrna/intern/rna_main_api.cc index 02dcc087047..459a2a1a6a6 100644 --- a/source/blender/makesrna/intern/rna_main_api.cc +++ b/source/blender/makesrna/intern/rna_main_api.cc @@ -269,7 +269,8 @@ static void rna_Main_materials_gpencil_remove(Main * /*bmain*/, PointerRNA *id_p ID *id = static_cast(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; } } diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo.cc b/source/blender/windowmanager/gizmo/intern/wm_gizmo.cc index 9ad2a07d68f..c85f91d0558 100644 --- a/source/blender/windowmanager/gizmo/intern/wm_gizmo.cc +++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo.cc @@ -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(gz)); } void WM_gizmo_unlink(ListBase *gizmolist, wmGizmoMap *gzmap, wmGizmo *gz, bContext *C) diff --git a/source/blender/windowmanager/intern/wm_operators.cc b/source/blender/windowmanager/intern/wm_operators.cc index cb3a67f0973..675ec7a570d 100644 --- a/source/blender/windowmanager/intern/wm_operators.cc +++ b/source/blender/windowmanager/intern/wm_operators.cc @@ -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(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(rc->dial)); + rc->dial = nullptr; + } } break; }