使用 std::vector 时的简单 Boost UDP 接收器 gest heap-use-after-free

Posted

技术标签:

【中文标题】使用 std::vector 时的简单 Boost UDP 接收器 gest heap-use-after-free【英文标题】:Simple Boost UDP receiver gest heap-use-after-free when using std::vector 【发布时间】:2021-03-22 14:30:28 【问题描述】:

我很难理解为什么我非常简单的 UDP 接收器会出现使用后无堆错误(由 ASAN 诊断)。这个想法是为传入的数据包侦听可配置数量的本地端口。

我在这里发布一个简化版的课程

UdpReceiver.hpp

class UdpReceiver

  public:
    UdpReceiver(std::vector<int> listen_ports);
    void run();
  protected:
    boost::asio::io_service m_io;
    char m_receive_buffer[MAX_RECEIVE_LENGTH];
    std::vector<udp::endpoint> m_endpoints;
    std::vector<udp::socket> m_sockets;
    void handleUdpData(const boost::system::error_code& error, size_t bytes_recvd, int idx);

; 

UdpReceiver.cpp

UdpReceiver::UdpReceiver(std::vector<int> listen_ports) : 
  m_io()
 
  
  int idx = 0;
  try 
  for (auto port: listen_ports) 
    m_endpoints.push_back(udp::endpoint(udp::v4(), port));
    m_sockets.push_back(udp::socket(m_io, m_endpoints[idx]));
    m_sockets[idx].async_receive_from(
      boost::asio::buffer(m_receive_buffer, MAX_RECEIVE_LENGTH), m_endpoints[idx],
      boost::bind(&MessageParser::handleUdpData, this,
      boost::asio::placeholders::error,
      boost::asio::placeholders::bytes_transferred,
      idx)
    );
    idx++;
  
   catch(const std::exception &exc) 
  
    std::cerr <<exc.what();
    exit(-1);
  

根据 ASAN m_endpoints.push_back(udp::endpoint(udp::v4(), port)) 分配一些动态内存,这些内存会在以后的迭代中再次释放。这最终给了我 use-after-free,它以一种不可预知的方式弄乱了我的应用程序。

我真的无法理解在这种情况下如何使用 std::vector 。有什么想法吗?

【问题讨论】:

是的,将东西推到向量可以移动整个向量。 【参考方案1】:

async_receive_from 的文档说:“调用者保留 sender_endpoint 对象的所有权,它必须保证在调用处理程序之前它是有效的。”

您的push_backs 可能会重新分配底层存储空间,从而使async_receive_from 留下一个悬空引用。

为避免重新分配,请在进入循环之前为必要数量的元素保留空间:

m_endpoints.reserve(listen_ports.size());
m_sockets.reserve(listen_ports.size());

【讨论】:

以上是关于使用 std::vector 时的简单 Boost UDP 接收器 gest heap-use-after-free的主要内容,如果未能解决你的问题,请参考以下文章

std::vector<float> 成员的 boost 序列化/反序列化失败

使用 boost::python vector_indexing_suite 包装 std::vector

如何使用 boost::serialization 序列化 std::vector?

如何使用 std::vector 初始化 boost::random::discrete_distribution?

boost::container::vector 和 std::vector 有啥区别

在 boost::asio::buffer 中使用类似 std::vector<std::complex<double>> 的参数