Cleanup: nodes: Replace 'void' MEM_[cm]allocN with templated, type-safe MEM_[cm]allocN<T>.

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<T> 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/135855
This commit is contained in:
Bastien Montagne
2025-03-12 12:15:33 +01:00
committed by Bastien Montagne
parent a65569f367
commit 78969aaff8
14 changed files with 27 additions and 33 deletions

View File

@@ -35,8 +35,7 @@ static void CMP_NODE_CONVERT_COLOR_SPACE_declare(NodeDeclarationBuilder &b)
static void node_composit_init_convert_colorspace(bNodeTree * /*ntree*/, bNode *node)
{
NodeConvertColorSpace *ncs = static_cast<NodeConvertColorSpace *>(
MEM_callocN(sizeof(NodeConvertColorSpace), "node colorspace"));
NodeConvertColorSpace *ncs = MEM_callocN<NodeConvertColorSpace>("node colorspace");
const char *first_colorspace = IMB_colormanagement_role_colorspace_name_get(
COLOR_ROLE_SCENE_LINEAR);
if (first_colorspace && first_colorspace[0]) {

View File

@@ -710,8 +710,8 @@ class FileOutputOperation : public NodeOperation {
switch (result.type()) {
case ResultType::Float: {
float *buffer = static_cast<float *>(MEM_malloc_arrayN(
size_t(size.x) * size.y, sizeof(float), "File Output Inflated Buffer."));
float *buffer = MEM_malloc_arrayN<float>(size_t(size.x) * size_t(size.y),
"File Output Inflated Buffer.");
const float value = result.get_single_value<float>();
parallel_for(
@@ -719,8 +719,8 @@ class FileOutputOperation : public NodeOperation {
return buffer;
}
case ResultType::Color: {
float *buffer = static_cast<float *>(MEM_malloc_arrayN(
size_t(size.x) * size.y, sizeof(float[4]), "File Output Inflated Buffer."));
float *buffer = MEM_malloc_arrayN<float>(4 * size_t(size.x) * size_t(size.y),
"File Output Inflated Buffer.");
const float4 value = result.get_single_value<float4>();
parallel_for(size, [&](const int2 texel) {
@@ -729,8 +729,8 @@ class FileOutputOperation : public NodeOperation {
return buffer;
}
case ResultType::Float4: {
float *buffer = static_cast<float *>(MEM_malloc_arrayN(
size_t(size.x) * size.y, sizeof(float[4]), "File Output Inflated Buffer."));
float *buffer = MEM_malloc_arrayN<float>(4 * size_t(size.x) * size_t(size.y),
"File Output Inflated Buffer.");
const float4 value = result.get_single_value<float4>();
parallel_for(size, [&](const int2 texel) {
@@ -739,8 +739,8 @@ class FileOutputOperation : public NodeOperation {
return buffer;
}
case ResultType::Float3: {
float *buffer = static_cast<float *>(MEM_malloc_arrayN(
size_t(size.x) * size.y, sizeof(float[3]), "File Output Inflated Buffer."));
float *buffer = MEM_malloc_arrayN<float>(3 * size_t(size.x) * size_t(size.y),
"File Output Inflated Buffer.");
const float3 value = result.get_single_value<float3>();
parallel_for(size, [&](const int2 texel) {
@@ -808,8 +808,8 @@ class FileOutputOperation : public NodeOperation {
* input image is freed. */
float *float4_to_float3_image(int2 size, float *float4_image)
{
float *float3_image = static_cast<float *>(MEM_malloc_arrayN(
size_t(size.x) * size.y, sizeof(float[3]), "File Output Vector Buffer."));
float *float3_image = MEM_malloc_arrayN<float>(3 * size_t(size.x) * size_t(size.y),
"File Output Vector Buffer.");
parallel_for(size, [&](const int2 texel) {
for (int i = 0; i < 3; i++) {

View File

@@ -310,8 +310,7 @@ static void cmp_node_rlayer_create_outputs(bNodeTree *ntree,
if (engine_type && engine_type->update_render_passes) {
ViewLayer *view_layer = (ViewLayer *)BLI_findlink(&scene->view_layers, node->custom1);
if (view_layer) {
RLayerUpdateData *data = (RLayerUpdateData *)MEM_mallocN(sizeof(RLayerUpdateData),
"render layer update data");
RLayerUpdateData *data = MEM_mallocN<RLayerUpdateData>("render layer update data");
data->available_sockets = available_sockets;
data->prev_index = -1;
node->storage = data;

View File

@@ -30,7 +30,7 @@ static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
static void node_init(bNodeTree * /*tree*/, bNode *node)
{
node->storage = MEM_callocN(sizeof(NodeInputString), __func__);
node->storage = MEM_callocN<NodeInputString>(__func__);
}
static void node_storage_free(bNode *node)

View File

@@ -198,8 +198,7 @@ static void node_geo_exec(GeoNodeExecParams params)
}
MEM_SAFE_FREE(result->mat);
result->mat = static_cast<Material **>(
MEM_malloc_arrayN(materials.size(), sizeof(Material *), __func__));
result->mat = MEM_malloc_arrayN<Material *>(size_t(materials.size()), __func__);
result->totcol = materials.size();
MutableSpan(result->mat, result->totcol).copy_from(materials);

View File

@@ -185,7 +185,7 @@ static std::optional<TextLayout> get_text_layout(GeoNodeExecParams &params)
cu.linedist = line_spacing;
cu.vfont = vfont;
cu.overflow = overflow;
cu.tb = static_cast<TextBox *>(MEM_calloc_arrayN(MAXTEXTBOX, sizeof(TextBox), __func__));
cu.tb = MEM_calloc_arrayN<TextBox>(MAXTEXTBOX, __func__);
cu.tb->w = textbox_w;
cu.tb->h = textbox_h;
cu.totbox = 1;
@@ -197,7 +197,7 @@ static std::optional<TextLayout> get_text_layout(GeoNodeExecParams &params)
/* The reason for the additional character here is unknown, but reflects other code elsewhere. */
cu.str = static_cast<char *>(MEM_mallocN(len_bytes + sizeof(char32_t), __func__));
memcpy(cu.str, layout.text.c_str(), len_bytes + 1);
cu.strinfo = static_cast<CharInfo *>(MEM_callocN((len_chars + 1) * sizeof(CharInfo), __func__));
cu.strinfo = MEM_calloc_arrayN<CharInfo>(len_chars + 1, __func__);
CharTrans *chartransdata = nullptr;
int text_len;

View File

@@ -145,7 +145,7 @@ std::unique_ptr<IDProperty, bke::idprop::IDPropertyDeleter> id_property_create_f
ui_data->base.rna_subtype = value->subtype;
ui_data->soft_min = double(value->min);
ui_data->soft_max = double(value->max);
ui_data->default_array = (double *)MEM_mallocN(sizeof(double[3]), "mod_prop_default");
ui_data->default_array = MEM_malloc_arrayN<double>(3, "mod_prop_default");
ui_data->default_array_len = 3;
for (const int i : IndexRange(3)) {
ui_data->default_array[i] = double(value->value[i]);
@@ -160,7 +160,7 @@ std::unique_ptr<IDProperty, bke::idprop::IDPropertyDeleter> id_property_create_f
Span<float>{value->value[0], value->value[1], value->value[2], value->value[3]});
IDPropertyUIDataFloat *ui_data = (IDPropertyUIDataFloat *)IDP_ui_data_ensure(property.get());
ui_data->base.rna_subtype = PROP_COLOR;
ui_data->default_array = (double *)MEM_mallocN(sizeof(double[4]), __func__);
ui_data->default_array = MEM_malloc_arrayN<double>(4, __func__);
ui_data->default_array_len = 4;
ui_data->min = 0.0;
ui_data->max = FLT_MAX;

View File

@@ -187,11 +187,10 @@ bNodeTreeExec *ntree_exec_begin(bNodeExecContext *context,
/* allocated exec data pointers for nodes */
exec->totnodes = nodelist.size();
exec->nodeexec = (bNodeExec *)MEM_callocN(exec->totnodes * sizeof(bNodeExec),
"node execution data");
exec->nodeexec = MEM_calloc_arrayN<bNodeExec>(size_t(exec->totnodes), "node execution data");
/* allocate data pointer for node stack */
exec->stacksize = index;
exec->stack = (bNodeStack *)MEM_callocN(exec->stacksize * sizeof(bNodeStack), "bNodeStack");
exec->stack = MEM_calloc_arrayN<bNodeStack>(size_t(exec->stacksize), "bNodeStack");
/* all non-const results are considered inputs */
int n;

View File

@@ -1282,8 +1282,7 @@ bNodeTreeExec *ntreeShaderBeginExecTree_internal(bNodeExecContext *context,
bNodeTreeExec *exec = ntree_exec_begin(context, ntree, parent_key);
/* allocate the thread stack listbase array */
exec->threadstack = static_cast<ListBase *>(
MEM_callocN(BLENDER_MAX_THREADS * sizeof(ListBase), "thread stack array"));
exec->threadstack = MEM_calloc_arrayN<ListBase>(BLENDER_MAX_THREADS, "thread stack array");
LISTBASE_FOREACH (bNode *, node, &exec->nodetree->nodes) {
node->runtime->need_exec = 1;

View File

@@ -29,7 +29,7 @@ static int node_shader_gpu_blackbody(GPUMaterial *mat,
GPUNodeStack *out)
{
const int size = CM_TABLE + 1;
float *data = static_cast<float *>(MEM_mallocN(sizeof(float) * size * 4, "blackbody texture"));
float *data = MEM_malloc_arrayN<float>(size * 4, "blackbody texture");
IMB_colormanagement_blackbody_temperature_to_rgb_table(data, size, 800.0f, 12000.0f);

View File

@@ -73,8 +73,7 @@ static void node_shader_buts_tex_pointdensity(uiLayout *layout, bContext * /*C*/
static void node_shader_init_tex_pointdensity(bNodeTree * /*ntree*/, bNode *node)
{
NodeShaderTexPointDensity *point_density = static_cast<NodeShaderTexPointDensity *>(
MEM_callocN(sizeof(NodeShaderTexPointDensity), __func__));
NodeShaderTexPointDensity *point_density = MEM_callocN<NodeShaderTexPointDensity>(__func__);
point_density->resolution = 100;
point_density->radius = 0.3f;
point_density->space = SHD_POINTDENSITY_SPACE_OBJECT;

View File

@@ -124,11 +124,11 @@ static int node_shader_gpu_volume_principled(GPUMaterial *mat,
const int size = CM_TABLE + 1;
float *data, layer;
if (use_blackbody) {
data = (float *)MEM_mallocN(sizeof(float) * size * 4, "blackbody texture");
data = MEM_malloc_arrayN<float>(size * 4, "blackbody texture");
IMB_colormanagement_blackbody_temperature_to_rgb_table(data, size, 800.0f, 12000.0f);
}
else {
data = (float *)MEM_callocN(sizeof(float) * size * 4, "blackbody black");
data = MEM_calloc_arrayN<float>(size * 4, "blackbody black");
}
GPUNodeLink *spectrummap = GPU_color_band(mat, size, data, &layer);

View File

@@ -25,7 +25,7 @@ static int node_shader_gpu_wavelength(GPUMaterial *mat,
GPUNodeStack *out)
{
const int size = CM_TABLE + 1;
float *data = static_cast<float *>(MEM_mallocN(sizeof(float) * size * 4, "cie_xyz texture"));
float *data = MEM_malloc_arrayN<float>(size * 4, "cie_xyz texture");
IMB_colormanagement_wavelength_to_rgb_table(data, size);

View File

@@ -240,7 +240,7 @@ ProcDef(stucci);
static void init(bNodeTree * /*ntree*/, bNode *node)
{
Tex *tex = static_cast<Tex *>(MEM_callocN(sizeof(Tex), "Tex"));
Tex *tex = MEM_callocN<Tex>("Tex");
node->storage = tex;
BKE_texture_default(tex);