From 1ff24efa020ea06adc6f8f9c26ae6ed8097816bb Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Tue, 18 Mar 2025 10:14:53 +0100 Subject: [PATCH] Cleanup: ikplugin: Replace 'void' MEM_[cm]allocN with templated, type-safe MEM_[cm]allocN. The main issue of 'type-less' standard C allocations is that there is no check on allocated type possible. This is a serious source of annoyance (and crashes) when making some low-level structs non-trivial, as tracking down all usages of these structs in higher-level other structs and their allocation is... really painful. MEM_[cm]allocN templates on the other hand do check that the given type is trivial, at build time (static assert), which makes such issue... trivial to catch. NOTE: New code should strive to use MEM_new (i.e. allocation and construction) as much as possible, even for trivial PoD types. Pull Request: https://projects.blender.org/blender/blender/pulls/136095 --- .../ikplugin/intern/iksolver_plugin.cc | 21 ++++++++----------- .../blender/ikplugin/intern/itasc_plugin.cc | 10 ++++----- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/source/blender/ikplugin/intern/iksolver_plugin.cc b/source/blender/ikplugin/intern/iksolver_plugin.cc index 337773ca157..1a471f7788a 100644 --- a/source/blender/ikplugin/intern/iksolver_plugin.cc +++ b/source/blender/ikplugin/intern/iksolver_plugin.cc @@ -116,13 +116,13 @@ static void initialize_posetree(Object * /*ob*/, bPoseChannel *pchan_tip) } /* create a target */ - target = static_cast(MEM_callocN(sizeof(PoseTarget), "posetarget")); + target = MEM_callocN("posetarget"); target->con = constraint; pchan_tip->flag &= ~POSE_CHAIN; if (tree == nullptr) { /* make new tree */ - tree = static_cast(MEM_callocN(sizeof(PoseTree), "posetree")); + tree = MEM_callocN("posetree"); tree->type = CONSTRAINT_TYPE_KINEMATIC; @@ -130,9 +130,8 @@ static void initialize_posetree(Object * /*ob*/, bPoseChannel *pchan_tip) tree->totchannel = segcount; tree->stretch = (data->flag & CONSTRAINT_IK_STRETCH); - tree->pchan = static_cast( - MEM_callocN(segcount * sizeof(void *), "ik tree pchan")); - tree->parent = static_cast(MEM_callocN(segcount * sizeof(int), "ik tree parent")); + tree->pchan = MEM_calloc_arrayN(size_t(segcount), "ik tree pchan"); + tree->parent = MEM_calloc_arrayN(size_t(segcount), "ik tree parent"); for (int a = 0; a < segcount; a++) { tree->pchan[a] = chanlist[segcount - a - 1]; tree->parent[a] = a - 1; @@ -186,9 +185,8 @@ static void initialize_posetree(Object * /*ob*/, bPoseChannel *pchan_tip) oldchan = tree->pchan; int *oldparent = tree->parent; - tree->pchan = static_cast( - MEM_callocN(newsize * sizeof(void *), "ik tree pchan")); - tree->parent = static_cast(MEM_callocN(newsize * sizeof(int), "ik tree parent")); + tree->pchan = MEM_calloc_arrayN(size_t(newsize), "ik tree pchan"); + tree->parent = MEM_calloc_arrayN(size_t(newsize), "ik tree parent"); memcpy(tree->pchan, oldchan, sizeof(void *) * tree->totchannel); memcpy(tree->parent, oldparent, sizeof(int) * tree->totchannel); MEM_freeN(oldchan); @@ -307,7 +305,7 @@ static void execute_posetree(Depsgraph *depsgraph, Scene *scene, Object *ob, Pos return; } - iktree = static_cast(MEM_mallocN(sizeof(void *) * tree->totchannel, "ik tree")); + iktree = MEM_malloc_arrayN(size_t(tree->totchannel), "ik tree"); for (a = 0; a < tree->totchannel; a++) { float length; @@ -526,10 +524,9 @@ static void execute_posetree(Depsgraph *depsgraph, Scene *scene, Object *ob, Pos IK_FreeSolver(solver); /* gather basis changes */ - tree->basis_change = static_cast( - MEM_mallocN(sizeof(float[3][3]) * tree->totchannel, "ik basis change")); + tree->basis_change = MEM_malloc_arrayN(size_t(tree->totchannel), "ik basis change"); if (hasstretch) { - ikstretch = static_cast(MEM_mallocN(sizeof(float) * tree->totchannel, "ik stretch")); + ikstretch = MEM_malloc_arrayN(size_t(tree->totchannel), "ik stretch"); } for (a = 0; a < tree->totchannel; a++) { diff --git a/source/blender/ikplugin/intern/itasc_plugin.cc b/source/blender/ikplugin/intern/itasc_plugin.cc index adf2494b058..bf1f433c8f9 100644 --- a/source/blender/ikplugin/intern/itasc_plugin.cc +++ b/source/blender/ikplugin/intern/itasc_plugin.cc @@ -284,8 +284,8 @@ static int initialize_chain(Object * /*ob*/, bPoseChannel *pchan_tip, bConstrain tree->totchannel = segcount; tree->stretch = (data->flag & CONSTRAINT_IK_STRETCH); - tree->pchan = (bPoseChannel **)MEM_callocN(segcount * sizeof(void *), "ik tree pchan"); - tree->parent = (int *)MEM_callocN(segcount * sizeof(int), "ik tree parent"); + tree->pchan = MEM_calloc_arrayN(size_t(segcount), "ik tree pchan"); + tree->parent = MEM_calloc_arrayN(size_t(segcount), "ik tree parent"); for (a = 0; a < segcount; a++) { tree->pchan[a] = chanlist[segcount - a - 1]; tree->parent[a] = a - 1; @@ -339,8 +339,8 @@ static int initialize_chain(Object * /*ob*/, bPoseChannel *pchan_tip, bConstrain oldchan = tree->pchan; oldparent = tree->parent; - tree->pchan = (bPoseChannel **)MEM_callocN(newsize * sizeof(void *), "ik tree pchan"); - tree->parent = (int *)MEM_callocN(newsize * sizeof(int), "ik tree parent"); + tree->pchan = MEM_calloc_arrayN(size_t(newsize), "ik tree pchan"); + tree->parent = MEM_calloc_arrayN(size_t(newsize), "ik tree parent"); memcpy(tree->pchan, oldchan, sizeof(void *) * tree->totchannel); memcpy(tree->parent, oldparent, sizeof(int) * tree->totchannel); MEM_freeN(oldchan); @@ -414,7 +414,7 @@ static IK_Data *get_ikdata(bPose *pose) if (pose->ikdata) { return (IK_Data *)pose->ikdata; } - pose->ikdata = MEM_callocN(sizeof(IK_Data), "iTaSC ikdata"); + pose->ikdata = MEM_callocN("iTaSC ikdata"); /* here init ikdata if needed * now that we have scene, make sure the default param are initialized */ if (!DefIKParam.iksolver) {