我正在尝试访问使用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 。代码有什么问题?

c&#43;&#43; - 从boost创建的缓冲区访问数据-LMLPHP

最佳答案

问题是造成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指向哪里。因此,没有人保证程序会以正确或错误的方式执行。

09-07 06:48
查看更多