C++ boost asio 奇怪的缓冲区溢出

问题描述

我已经调试了 2 天了。我试过更简单的代码库,据说可以重现这个错误……但它们工作得很好。我不确定该错误是否与我滥用 boost asio 函数或其他一些 C++ 功能有关。

我正在写一个 TCP 服务器,其中的消息结构定义为:

uint64_t size      // Size of the message,in bytes
uint64_t timestamp // Some timestamp
char    *text      // Some ASCII data

代码

表示 sizetimestamp 的 Header 类声明为:

class Header {
private:
    uint64_t buf[2];

    void *data() const {
        return (void *) &buf[0];
    }

public:
    Header() {
        buf[0] = 0UL;
        buf[1] = 0UL;
    }
    
    // Reads the header from the socket
    void readHeader(boost::asio::ip::tcp::socket &socket,std::function<void (void)> cb);

    std::size_t getHeaderSize() const {
        return sizeof(buf);
    }

    uint64_t getDatagramSize() const {
        return buf[0];
    }

    uint64_t getTimestamp() const {
        return buf[1];
    }

};

ImuDatagram 包含整个消息,并具有从套接字读取数据报的方法

class ImuDatagram {

public:
    Header header;
    std::string theJson;

    void readDatagram(boost::asio::ip::tcp::socket &socket,std::function<void (void)> cb);
    void readBody(boost::asio::ip::tcp::socket &socket,std::function<void (void)> cb);

};

方法定义如下:

void Header::readHeader(boost::asio::ip::tcp::socket &socket,std::function<void (void)> cb)
{
    boost::asio::mutable_buffer asio_buf = boost::asio::buffer(data(),getHeaderSize());
    boost::asio::async_read(socket,asio_buf,[this,cb](const boost::system::error_code &ec,std::size_t bytes_transferred){
                // TAG1
                // bytes_transferred: 16 (as expected)
                // getDatagramSize() == 116 (as expected)
                // getTimestamp() == ... (as expected)
                
                cb();
        });
}

void ImuDatagram::readBody(boost::asio::ip::tcp::socket &socket,std::function<void (void)> cb) {
    uint64_t dgSize = header.getDatagramSize();
    uint64_t jsonSize = dgSize - header.getHeaderSize();
    // TAG2
    // This will throw std::bad_alloc.
    theJson.reserve(jsonSize);

    boost::asio::async_read(socket,boost::asio::buffer(theJson,jsonSize),&socket,std::size_t bytes_transferred) {
            // Error checks omitted

            cb();
        });
}

void ImuDatagram::readDatagram(boost::asio::ip::tcp::socket &socket,std::function<void (void)> cb) {

    header.readHeader(socket,cb](){
        readBody(socket,cb);
    });
}

最后,让一切顺利的 main 是:

tcp::acceptor imuAcceptor(ioc,tcp::endpoint(tcp::v4(),8081));
imuAcceptor.async_accept(imuSocket,[this](const boost::system::error_code& ec)
    {
        // Error checks omitted
        ImuDatagram imu;
        imu.readDatagram(socket,&imu,&socket]() {
            // Do work
        });
    }

问题描述

  1. 考虑 TAG1 中的 Header::readHeader。正如预期的那样,读取了 16 个字节(标头缓冲区的大小)。我确认 theJson 的缓冲区没有溢出。还没有错。
  2. 然后我们移至 TAG2 中的 ImuDatagram::readBody。如上所述,这会抛出 std::bad_alloc

作为调试的一部分,我在标头后插入了一个 protection 字节,以查看它是否会被写入。在 TAG1 处,未写入。在TAG2,它被写入。起初,我以为 async_read 正在写入缓冲区。但事实并非如此,正如我添加protection 字节所验证的那样。

谁能告诉我这个(对我来说很模糊)错误在哪里?我使用 STDIN 而不是套接字编写了一个更简单的版本,它工作得很好。我怀疑问题不是来自套接字。

谢谢。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)