From 891a2bee88b164410b666e9f74e3a61479fe0536 Mon Sep 17 00:00:00 2001 From: Hyoung Joo Ahn Date: Wed, 23 Jan 2019 12:58:23 +0900 Subject: [PATCH] [Filter] fix the memory leak at filter this pr solves the memory leak problem about the `model_file` and the `name` of input/output tensor Signed-off-by: Hyoung Joo Ahn --- gst/nnstreamer/tensor_filter/tensor_filter.c | 96 +++++++++++++++++-- .../custom_example_LSTM/dummy_LSTM.c | 17 +++- .../custom_example_RNN/dummy_RNN.c | 15 ++- ...treamer_customfilter_example_passthrough.c | 6 +- 4 files changed, 118 insertions(+), 16 deletions(-) diff --git a/gst/nnstreamer/tensor_filter/tensor_filter.c b/gst/nnstreamer/tensor_filter/tensor_filter.c index 86a4630667..ddf378706e 100644 --- a/gst/nnstreamer/tensor_filter/tensor_filter.c +++ b/gst/nnstreamer/tensor_filter/tensor_filter.c @@ -108,6 +108,7 @@ } \ } while (0) +#define g_free_const(x) g_free((void*)(long)(x)) typedef struct _TensorFilterSPList TensorFilterSPList; /** @@ -268,6 +269,7 @@ static void gst_tensor_filter_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); static void gst_tensor_filter_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); +static void gst_tensor_filter_finalize (GObject * object); /* GstBaseTransform vmethod implementations */ static GstFlowReturn gst_tensor_filter_transform (GstBaseTransform * trans, @@ -308,7 +310,8 @@ static gboolean gst_tensor_filter_stop (GstBaseTransform * trans); if (filter->fw && filter->fw->close) \ filter->fw->close (filter, &filter->privateData); \ filter->prop.fw_opened = FALSE; \ - g_free ((char *) filter->prop.fwname); \ + g_free_const (filter->prop.fwname); \ + filter->prop.fwname = NULL; \ filter->fw = NULL; \ } \ } while (0) @@ -340,6 +343,7 @@ gst_tensor_filter_class_init (GstTensorFilterClass * klass) gobject_class->set_property = gst_tensor_filter_set_property; gobject_class->get_property = gst_tensor_filter_get_property; + gobject_class->finalize = gst_tensor_filter_finalize; g_object_class_install_property (gobject_class, PROP_SILENT, g_param_spec_boolean ("silent", "Silent", "Produce verbose output", @@ -447,6 +451,66 @@ gst_tensor_filter_init (GstTensorFilter * self) gst_tensors_config_init (&self->out_config); } +/** + * @brief deallocate the name of each GstTensorInfo. + * @param The GstTensorsInfo object + */ +inline void +gst_tensor_filter_deallocate_tensor_name (GstTensorsInfo * info) +{ + guint i; + for (i = 0; i < info->num_tensors; ++i) + g_free (info->info[i].name); + gst_tensors_info_init (info); +} + +/** + * @brief Clear and reset data. + */ +static void +gst_tensor_filter_reset (GstTensorFilter * self) +{ + GstTensorFilterProperties *prop; + + prop = &self->prop; + + gst_tensor_filter_close_fw (self); + + g_free_const (prop->fwname); + prop->fwname = NULL; + + g_free_const (prop->model_file); + prop->model_file = NULL; + + g_free_const (prop->custom_properties); + prop->custom_properties = NULL; + + prop->input_configured = FALSE; + gst_tensor_filter_deallocate_tensor_name (&prop->input_meta); + + prop->output_configured = FALSE; + gst_tensor_filter_deallocate_tensor_name (&prop->output_meta); + + self->configured = FALSE; + gst_tensors_config_init (&self->in_config); + gst_tensors_config_init (&self->out_config); +} + +/** + * @brief Function to finalize instance. + */ +static void +gst_tensor_filter_finalize (GObject * object) +{ + GstTensorFilter *self; + + self = GST_TENSOR_FILTER (object); + + gst_tensor_filter_reset (self); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + /** * @brief Calculate output buffer size. * @param self "this" pointer @@ -515,7 +579,7 @@ gst_tensor_filter_set_property (GObject * object, guint prop_id, break; } - g_free ((char *) prop->fwname); + g_free_const (prop->fwname); prop->fwname = g_strdup (fw_name); /* See if mandatory methods are filled in */ @@ -530,7 +594,7 @@ gst_tensor_filter_set_property (GObject * object, guint prop_id, if (prop->model_file) { gst_tensor_filter_close_fw (self); - g_free ((char *) prop->model_file); /* g_free cannot handle const * */ + g_free_const (prop->model_file); prop->model_file = NULL; } @@ -659,7 +723,7 @@ gst_tensor_filter_set_property (GObject * object, guint prop_id, break; case PROP_CUSTOM: /* In case updated custom properties in runtime! */ - g_free ((char *) prop->custom_properties); /* g_free cannot handle const char * */ + g_free_const (prop->custom_properties); prop->custom_properties = g_value_dup_string (value); silent_debug ("Custom Option = %s\n", prop->custom_properties); break; @@ -1016,6 +1080,26 @@ _compare_tensors (GstTensorsInfo * info1, GstTensorsInfo * info2) return result; } +/** + * @brief Copy GstTensorsInfo without the name of tensors. + * @param[out] the destination object + * @param[in] the source object + */ +static void +gst_tensor_filter_copy_info (GstTensorsInfo * dest, const GstTensorsInfo * src) +{ + guint i; + + g_return_if_fail (dest != NULL && src != NULL); + + dest->num_tensors = src->num_tensors; + for (i = 0; i < src->num_tensors; ++i) { + memcpy (dest->info[i].dimension, src->info[i].dimension, + sizeof (tensor_dim)); + dest->info[i].type = src->info[i].type; + } +} + /** * @brief Configure input and output tensor info from incaps. * @param self "this" pointer @@ -1062,7 +1146,7 @@ gst_tensor_filter_configure_tensor (GstTensorFilter * self, } prop->input_configured = TRUE; - prop->input_meta = in_config.info; + gst_tensor_filter_copy_info (&prop->input_meta, &in_config.info); /** call setInputDimension if output tensor is not configured */ if (!prop->output_configured) { @@ -1086,7 +1170,7 @@ gst_tensor_filter_configure_tensor (GstTensorFilter * self, } prop->output_configured = TRUE; - prop->output_meta = out_info; + gst_tensor_filter_copy_info (&prop->output_meta, &out_info); silent_debug_info (&out_info, "output tensor"); } diff --git a/nnstreamer_example/custom_example_LSTM/dummy_LSTM.c b/nnstreamer_example/custom_example_LSTM/dummy_LSTM.c index d9b5532e6e..228490fbfc 100644 --- a/nnstreamer_example/custom_example_LSTM/dummy_LSTM.c +++ b/nnstreamer_example/custom_example_LSTM/dummy_LSTM.c @@ -75,14 +75,17 @@ get_inputDim (void *private_data, const GstTensorFilterProperties * prop, GstTensorsInfo * info) { pt_data *data = private_data; + int i; assert (data); assert (NNS_TENSOR_RANK_LIMIT >= 3); info->num_tensors = 3; - info->info[0] = data->info[0]; - info->info[1] = data->info[1]; - info->info[2] = data->info[2]; + for (i = 0; i < info->num_tensors; ++i) { + memcpy (info->info[i].dimension, data->info[i].dimension, + sizeof (tensor_dim)); + info->info[i].type = data->info[i].type; + } return 0; } @@ -94,13 +97,17 @@ get_outputDim (void *private_data, const GstTensorFilterProperties * prop, GstTensorsInfo * info) { pt_data *data = private_data; + int i; assert (data); assert (NNS_TENSOR_RANK_LIMIT >= 3); info->num_tensors = 2; - info->info[0] = data->info[0]; - info->info[1] = data->info[1]; + for (i = 0; i < info->num_tensors; ++i) { + memcpy (info->info[i].dimension, data->info[i].dimension, + sizeof (tensor_dim)); + info->info[i].type = data->info[i].type; + } return 0; } diff --git a/nnstreamer_example/custom_example_RNN/dummy_RNN.c b/nnstreamer_example/custom_example_RNN/dummy_RNN.c index 17af1128e7..1e4c2e972a 100644 --- a/nnstreamer_example/custom_example_RNN/dummy_RNN.c +++ b/nnstreamer_example/custom_example_RNN/dummy_RNN.c @@ -73,13 +73,17 @@ get_inputDim (void *private_data, const GstTensorFilterProperties * prop, GstTensorsInfo * info) { pt_data *data = private_data; + int i; assert (data); assert (NNS_TENSOR_RANK_LIMIT >= 3); info->num_tensors = 2; - info->info[0] = data->info[0]; - info->info[1] = data->info[1]; + for (i = 0; i < info->num_tensors; ++i) { + memcpy (info->info[i].dimension, data->info[i].dimension, + sizeof (tensor_dim)); + info->info[i].type = data->info[i].type; + } return 0; } @@ -91,12 +95,17 @@ get_outputDim (void *private_data, const GstTensorFilterProperties * prop, GstTensorsInfo * info) { pt_data *data = private_data; + int i; assert (data); assert (NNS_TENSOR_RANK_LIMIT >= 3); info->num_tensors = 1; - info->info[0] = data->info[0]; + for (i = 0; i < info->num_tensors; ++i) { + memcpy (info->info[i].dimension, data->info[i].dimension, + sizeof (tensor_dim)); + info->info[i].type = data->info[i].type; + } return 0; } diff --git a/nnstreamer_example/custom_example_passthrough/nnstreamer_customfilter_example_passthrough.c b/nnstreamer_example/custom_example_passthrough/nnstreamer_customfilter_example_passthrough.c index dfa2df98f9..e55a738e7b 100644 --- a/nnstreamer_example/custom_example_passthrough/nnstreamer_customfilter_example_passthrough.c +++ b/nnstreamer_example/custom_example_passthrough/nnstreamer_customfilter_example_passthrough.c @@ -96,7 +96,8 @@ get_inputDim (void *private_data, const GstTensorFilterProperties * prop, assert (NNS_TENSOR_RANK_LIMIT >= 3); info->num_tensors = 1; - info->info[0] = data->info; + memcpy (info->info[0].dimension, data->info.dimension, sizeof (tensor_dim)); + info->info[0].type = data->info.type; return 0; } @@ -113,7 +114,8 @@ get_outputDim (void *private_data, const GstTensorFilterProperties * prop, assert (NNS_TENSOR_RANK_LIMIT >= 3); info->num_tensors = 1; - info->info[0] = data->info; + memcpy (info->info[0].dimension, data->info.dimension, sizeof (tensor_dim)); + info->info[0].type = data->info.type; return 0; }