diff --git a/ext/rubydex/graph.c b/ext/rubydex/graph.c index 2c675351..8efc7c40 100644 --- a/ext/rubydex/graph.c +++ b/ext/rubydex/graph.c @@ -43,11 +43,7 @@ static VALUE rdxr_graph_index_all(VALUE self, VALUE file_paths) { size_t error_count = 0; const char *const *errors = rdx_index_all(graph, (const char **)converted_file_paths, length, &error_count); - // Free the converted file paths and allow the GC to collect them - for (size_t i = 0; i < length; i++) { - free(converted_file_paths[i]); - } - free(converted_file_paths); + rdxi_free_str_array(converted_file_paths, length); if (errors == NULL) { return rb_ary_new(); @@ -348,10 +344,7 @@ static VALUE rdxr_graph_resolve_constant(VALUE self, VALUE const_name, VALUE nes const CDeclaration *decl = rdx_graph_resolve_constant(graph, StringValueCStr(const_name), (const char **)converted_file_paths, length); - for (size_t i = 0; i < length; i++) { - free(converted_file_paths[i]); - } - free(converted_file_paths); + rdxi_free_str_array(converted_file_paths, length); if (decl == NULL) { return Qnil; @@ -379,10 +372,7 @@ static VALUE rdxr_graph_resolve_require_path(VALUE self, VALUE require_path, VAL const uint64_t *uri_id = rdx_resolve_require_path(graph, path_str, (const char **)converted_paths, paths_len); - for (size_t i = 0; i < paths_len; i++) { - free(converted_paths[i]); - } - free(converted_paths); + rdxi_free_str_array(converted_paths, paths_len); if (uri_id == NULL) { return Qnil; @@ -407,10 +397,7 @@ static VALUE rdxr_graph_require_paths(VALUE self, VALUE load_path) { size_t out_count = 0; const char *const *results = rdx_require_paths(graph, (const char **)converted_paths, paths_len, &out_count); - for (size_t i = 0; i < paths_len; i++) { - free(converted_paths[i]); - } - free(converted_paths); + rdxi_free_str_array(converted_paths, paths_len); if (results == NULL) { return rb_ary_new(); diff --git a/ext/rubydex/utils.c b/ext/rubydex/utils.c index ac340875..d7a8d126 100644 --- a/ext/rubydex/utils.c +++ b/ext/rubydex/utils.c @@ -19,6 +19,16 @@ char **rdxi_str_array_to_char(VALUE array, size_t length) { return converted_array; } +// Free a char** array allocated by rdxi_str_array_to_char +void rdxi_free_str_array(char **array, size_t length) { + if (array != NULL) { + for (size_t i = 0; i < length; i++) { + free(array[i]); + } + free(array); + } +} + // Verify that the Ruby object is an array of strings or raise `TypeError` void rdxi_check_array_of_strings(VALUE array) { Check_Type(array, T_ARRAY); diff --git a/ext/rubydex/utils.h b/ext/rubydex/utils.h index 62b9d603..1998aa02 100644 --- a/ext/rubydex/utils.h +++ b/ext/rubydex/utils.h @@ -4,9 +4,12 @@ #include "ruby.h" // Convert a Ruby array of strings into a double char pointer so that we can pass that to Rust. -// This copies the data so it must be freed +// This copies the data so it must be freed with rdxi_free_str_array char **rdxi_str_array_to_char(VALUE array, size_t length); +// Free a char** array allocated by rdxi_str_array_to_char +void rdxi_free_str_array(char **array, size_t length); + // Verify that the Ruby object is an array of strings or raise `TypeError` void rdxi_check_array_of_strings(VALUE array);