diff --git a/rclcpp/src/rclcpp/utilities.cpp b/rclcpp/src/rclcpp/utilities.cpp index 2954133..b85b857 100644 --- a/rclcpp/src/rclcpp/utilities.cpp +++ b/rclcpp/src/rclcpp/utilities.cpp @@ -204,13 +204,13 @@ std::vector rclcpp::remove_ros_arguments(int argc, char const * const argv[]) { rcl_allocator_t alloc = rcl_get_default_allocator(); - rcl_arguments_t parsed_args; + rcl_arguments_t parsed_args = rcl_get_zero_initialized_arguments(); rcl_ret_t ret; ret = rcl_parse_arguments(argc, argv, alloc, &parsed_args); if (RCL_RET_OK != ret) { - exceptions::throw_from_rcl_error(ret, "Failed to parse arguments"); + exceptions::throw_from_rcl_error(ret, "failed to parse arguments"); } int nonros_argc = 0; @@ -224,10 +224,19 @@ rclcpp::remove_ros_arguments(int argc, char const * const argv[]) &nonros_argv); if (RCL_RET_OK != ret) { + // Not using throw_from_rcl_error, because we may need to append deallocation failures. + exceptions::RCLErrorBase base_exc(ret, rcl_get_error_state()); + rcl_reset_error(); if (NULL != nonros_argv) { alloc.deallocate(nonros_argv, alloc.state); } - exceptions::throw_from_rcl_error(ret, "Failed to remove ROS arguments: "); + if (RCL_RET_OK != rcl_arguments_fini(&parsed_args)) { + base_exc.formatted_message += std::string( + ", failed also to cleanup parsed arguments, leaking memory: ") + + rcl_get_error_string_safe(); + rcl_reset_error(); + } + throw exceptions::RCLError(base_exc, ""); } std::vector return_arguments; @@ -241,6 +250,11 @@ rclcpp::remove_ros_arguments(int argc, char const * const argv[]) alloc.deallocate(nonros_argv, alloc.state); } + ret = rcl_arguments_fini(&parsed_args); + if (RCL_RET_OK != ret) { + exceptions::throw_from_rcl_error(ret, "failed to cleanup parsed arguments, leaking memory"); + } + return return_arguments; }