ROS2 message memory allocations -- via micro_ros_utilities_create_*_message_memory() APIs -- seemingly causing data corruption

asked 2022-07-16 00:52:31 -0500

updated 2022-07-16 02:17:40 -0500

I am wrapping the microros rcl_service_t object within a C++ wrapper class, and I utilize micro_ros_utilities_create_static_message_memory() (and/or micro_ros_utilities_create_message_memory()) in the constructor, to setup the message memory etc.

Strangely, these allocation calls seem to be corrupting the memory of contiguous instance variables.

Here's a rough excerpt of the code (will not compile, but conveys the idea):

Service.h:

template <class RequestType, class ResponseType> 
class ServiceWrapper<RequestType, ResponseType> 
{ 
public:    
   ServiceWrapper(
         const std::string& name, 
         rcl_node_t* node, 
         rosidl_service_type_support_t * service_type_support, 
         rosidl_message_type_support_t * request_type_support, 
         rosidl_message_type_support_t * response_type_support, 
         ServiceCallback callback) 
  : name(name) {         // <------- Name argument is copied over via this member-initialization-list

       RCCHECK(rclc_service_init_default(&this->service_data, node, service_type_support, name.c_str()));

       Serial.printf("Name: %s", this->name.c_str());               // <----------- Prints is as expected

       // ~~~~~~~ TROUBLE CAUSING CODE (either or both calls) ~~~~~~~~~~~
       assert(micro_ros_utilities_create_message_memory(
                        request_type_support,
                        &this->request_msg, micro_ros_utilities_memory_conf_default));
       assert(micro_ros_utilities_create_message_memory(
                        response_type_support,
                        &this->response_msg, micro_ros_utilities_memory_conf_default));

       Serial.printf("Name: %s", this->name.c_str());              // <------------- The name variable gets corrupted by now
   }

private:    
   rcl_service_t     service_data; 
   RequestType    request_msg;    
   ResponseType  response_msg;
   std::string          name;              // <--------- Gets corrupted
};

The above code assumes the rcl_node_t has already been initialized, and the requisite rosidl-type-supports are provided as per the service and request/response message types.

I've printed out this->name two times to show the defect in action. The first time, it gets printed appropriately. However, the second time that is attempted, the behavior will be undefined (in my case it prints an empty string). The message initialization code between those two print statements seems to corrupt the memory of the contiguous instance variable(s) after the this->request_msg and this->response_msg types (in this case, this->name).

From an initial inspection, does this behavior seem like a microros bug, or am I invoking the memory initialization API incorrectly? I tried switching to micro_ros_utilities_create_message_memory() using additional instance variables (int buffers), but the behavior remains the same. Furthermore, the behavior may happen from either (or both) of the allocations -- request_msg or response_msg -- such that a certain number of bytes (not sure how many) of contiguous memory get corrupted, obviously yielding undefined behavior when eventually accessed.

edit retag flag offensive close merge delete