我正在尝试访问使用Boost缓冲区功能序列化的数据,并希望将其填充到两个 vector 中。我在填写第二个 vector 的地址时遇到问题。下一课将展示两个 vector 以及如何填充它们。
class LidarMeasurement {
private:
std::vector<uint32_t> _header;
std::vector<float> _azimuth;
public:
//The header consists of an array of uint32_t's in the following layout
enum Index : size_t {
HorizontalAngle,
ChannelCount,
SIZE
};
explicit LidarMeasurement(uint32_t NumOfChannels = 0u): _header(Index::SIZE + NumOfChannels, 0u) {
_header[Index::ChannelCount] = NumOfChannels;
}
// called before filling vectors
void Reset(uint32_t total_point_count) {
std::memset(_header.data() + Index::SIZE, 0, sizeof(uint32_t) * GetChannelCount());
_azimuth.clear();
_azimuth.reserve(total_point_count);
}
// after reset,Write point function starts filling vectors.. following function is called 104 times (not constant) before next reset
void WritePoint(uint32_t channel, float angle_hor) {
_header[Index::SIZE + channel] += 1u;
_azimuth.emplace_back(angle_hor);
}
uint32_t GetChannelCount() const {
return _header[Index::ChannelCount];
}
}
填充完毕后,将其序列化并发送给客户端。使用以下功能对其进行序列化:
template <typename Sensor>
inline Buffer LidarSerializer::Serialize(
const Sensor &,
const LidarMeasurement &measurement,
Buffer &&output) {
std::array<boost::asio::const_buffer, 2u> seq = {
boost::asio::buffer(measurement._header),
boost::asio::buffer(measurement._azimuth)};
output.copy_from(seq);
return std::move(output);
}
收到序列化数据后,需要将方位角放回 vector 。
我正在使用以下函数来获取 vector 。
_begin
是缓冲区的地址。std::vector<float> GetAzimuth(const uint32_t* _begin) const{
std::vector<float> localAzimuthMemCopy;
begin_azi = const_cast<float*>(reinterpret_cast<const float*>(_begin )) + (sizeof(uint32_t) * (GetChannelCount() + Index::SIZE));
end_azi = begin_azi + GetTotalPointCount();//Total point count is the addition of individual channel point counts (not shown here)
for(float* i = begin_azi; i < end_azi; i++){
localAzimuthMemCopy.emplace_back(*i);
}
return localAzimuthMemCopy;
}
但是,我得到的结果具有内存偏移量。我得到104个值,但最后18个值是垃圾。从错误的起始地址读取 vector 。代码有什么问题?
最佳答案
问题是造成bt错误开始地址计算的原因。begin_azi = const_cast<float*>(reinterpret_cast<const float*>(_begin )) + (sizeof(uint32_t) * (GetChannelCount() + Index::SIZE));
1)指针算术仅需要指针和元素个数即可前进。编译器应根据指针类型自行减去字节数。因此,在sizeof(uint32_t)
处的乘法是多余的。正确的指针前进方式显示在float* end_azi = begin_azi + GetTotalPointCount();
上
2)应该为指向uint32_t类型的指针计算地址偏移量,然后才将其转换为为浮点类型的指针。
因此,begin_azi
的正确方法应如下所示:begin_azi = const_cast<float*>(reinterpret_cast<const float*>(_begin + GetChannelCount() + Index::SIZE));
为什么它早先部分起作用?来自cppreference
没有人知道错误计算后指向的begin_azi
指向哪里。因此,没有人保证程序会以正确或错误的方式执行。