【发布时间】:2019-08-14 13:03:19
【问题描述】:
我正在尝试访问使用 boost 缓冲区函数序列化的数据,并希望将其填充到两个向量中。我在填写第二个向量的地址时遇到问题。下面的课程展示了这两个向量以及它们是如何填充的。
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);
}
收到序列化数据后,我需要将方位角放回矢量。
我正在使用以下函数来获取向量。 _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 个值是垃圾。从错误的起始地址读取向量。代码有什么问题?
【问题讨论】:
-
我把它改成了“NumOfChannels”避免混淆..!
-
我不太熟悉指针算术魔术,但我对
reinterpret_cast<const float*>(_begin )) + (sizeof(uint32_t) * (GetChannelCount() + Index::SIZE))感到困惑。您首先将指向 uint32_t 的指针转换为指向浮点数的指针,然后尝试推进整数字节。它在这一点上运作良好吗?据我记得,指针添加需要相同的类型,所以在这里你应该先将地址提前到 int 数组的末尾,然后将指针转换为 float。 -
uint32_t OFFSET = sizeof(uint32_t) * (GetChannelCount() + LidarMeasurement::Index::SIZE); begin_azi = const_cast<float*>(reinterpret_cast<const float*>(_begin + OFFSET));即使这样也行不通 -
GetTotalPointCount() 是什么?当您尝试调用 GetAzimuth 时,它的返回值是否大于或等于 104?
-
回到指针算术魔术。您不应该真正向编译器显示一个元素占用了多少字节,因此 sizeof(uint32_t) 处的元素数量相乘是不必要的。编译器应该只通过元素的类型和元素的数量来扣除它。
begin_azi = const_cast<float*>(reinterpret_cast<const float*>(_begin + GetChannelCount() + LidarMeasurement::Index::SIZE));请让我知道这条评论是否更有用。