How to correctly deserialize a message with variable length array?
I'm receiving some data from serial port and want to deserialize the byte stream I received to a ROS message.
The serial port data contains variable number of elements (elements with same type). So I use variable length array in my ROS message.
For example I have received these bytes in memory:
uint8_t buffer[] = { 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13 };
Here,
0x02
means 2 elements in the variable length array,(0x01010101, 0x02020202, 0x03030303)
is the first element, this is actually a 3-dimensional point with float type,(0x11111111, 0x12121212, 0x13131313)
is the second element.
And I'm going to use this message:
uint8 array_size # will be 0x02
geometry_msgs/Point32[] points # will be a array with length 2, the first Point32 is (0x01010101, 0x02020202, 0x03030303), and the second one is (0x11111111, 0x12121212, 0x13131313)
It seems the tutorial does not work with variable length array. I checked the code, and there is a serializer for std::vector
.
But the deserialization process goes wrong in this function:
// (line 348 of serialization.h)
template<typename Stream>
inline static void read(Stream& stream, VecType& v)
{
uint32_t len;
stream.next(len);
v.resize(len); // <----
IteratorType it = v.begin();
IteratorType end = v.end();
for (; it != end; ++it)
{
stream.next(*it);
}
}
It seems the deserializer will change the length of the vector first. But the value of variable len
gets very huge and v.resize(len)
fails.
You could try union. Why not use a vector instead of the dynamic array?
Note: the link (ie: "the code") points to the DiamondBack version of this. As this is really low-level functionality, it most likely hasn't changed in the important parts, but I would recommend you use either the repository that hosts the code, or at least use a more up-to-date set of documentation.