Boost buffer_cast 无法从 void* 转换为 PointerToPodType

Boost buffer_cast cannot convert from void* to PointerToPodType

我对Socket通信感兴趣,喜欢使用boost库。当我从服务器收到一条消息并尝试将其转换 atomic<uint8_t>* 时,它给了我一个 'static_cast': cannot convert from 'const void*' to 'PointerToPodType' 的错误。我不明白为什么它会给我那个错误。

代码示例

atomic<uint8_t>* buffer = new atomic<uint8_t>[10000];

boost::asio::streambuf receive_buffer;
boost::asio::read(*sock, receive_buffer, boost::asio::transfer_all(), this->ec);
    if (this->ec && this->ec != boost::asio::error::eof) {

        cout << "receive failed:" << this->ec.message() << endl;
    }
    else
    {
        ///ERROR IS HERE
        buffer = boost::asio::buffer_cast< atomic<uint8_t>*>(receive_buffer.data());

    }

不是C,不要用newmalloc(或deletefree)。

具体来说,我看到了指向套接字的指针,指向一切的指针。如果您使分配工作,您将泄漏用 new 分配的整个缓冲区。

这里有一个更简单的方法,削减了双缓冲(streambuf 增加了一点):

uint8_t buffer[10000];

auto transferred = boost::asio::read(
        sock,
        boost::asio::buffer(buffer),
        boost::asio::transfer_all(),
        ec);

现在成功了,tranferred 字节已经在您分配的缓冲区中了。使用 a

更简单
std::vector<uint8_t> buffer(10000);

因为这样你就可以

buffer.resize(transferred);

Live On Coliru

#include <boost/asio.hpp>
#include <atomic>
#include <iostream>
#include <iomanip>
using boost::asio::ip::tcp;
using boost::asio::ip::address_v4;

int main() {
    //uint8_t buffer[10000];
    std::vector<uint8_t> buffer(10000);

    boost::asio::io_context ioc;
    tcp::socket sock(ioc);
    sock.connect({address_v4::from_string("173.203.57.63"), 80});
    write(sock, boost::asio::buffer("GET / HTTP/1.1\r\nHost: coliru.stacked-crooked.com\r\nConnection: close\r\n\r\n"));

    boost::system::error_code ec;
    auto transferred = boost::asio::read(
            sock,
            boost::asio::buffer(buffer),
            boost::asio::transfer_all(),
            ec);

    if (ec && ec != boost::asio::error::eof) {
        std::cout << "receive failed:" << ec.message() << std::endl;
    } else {
        buffer.resize(transferred);
        std::cout << std::hex << std::showbase << std::setfill('0');
        int n = 0;
        for (int i : buffer) {
            std::cout
                << std::setw(4) << i
                << " '" << char(std::isgraph(i)?i : '.') << "'"
                << (++n % 8? ' ':'\n');
        }
    }
}

版画

g++ -std=c++17 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
0x48 'H' 0x54 'T' 0x54 'T' 0x50 'P' 0x2f '/' 0x31 '1' 0x2e '.' 0x31 '1'
0x20 '.' 0x32 '2' 0x30 '0' 0x30 '0' 0x20 '.' 0x4f 'O' 0x4b 'K' 0x20 '.'
00xd '.' 00xa '.' 0x43 'C' 0x6f 'o' 0x6e 'n' 0x74 't' 0x65 'e' 0x6e 'n'
0x74 't' 0x2d '-' 0x54 'T' 0x79 'y' 0x70 'p' 0x65 'e' 0x3a ':' 0x20 '.'
0x74 't' 0x65 'e' 0x78 'x' 0x74 't' 0x2f '/' 0x68 'h' 0x74 't' 0x6d 'm'
 ... 1100 lines snipped
0x20 '.' 0x20 '.' 0x7d '}' 0x3b ';' 00xa '.' 0x3c '<' 0x2f '/' 0x73 's'
0x63 'c' 0x72 'r' 0x69 'i' 0x70 'p' 0x74 't' 0x3e '>' 00xa '.' 0x3c '<'
0x2f '/' 0x68 'h' 0x74 't' 0x6d 'm' 0x6c 'l' 0x3e '>' 00xa '.' 

Dynamic/Heap分配

std::vector 已经进行了堆分配。如果您坚持使用原始 C 数组语义,请考虑 Live On Coliru:

 auto buffer = std::make_unique<std::array<std::atomic<uint8_t, 10'000> > >();
 // ...
        boost::asio::buffer(*buffer),
 // ...
    size_t n = 0;
    for (int i : *buffer) {
        if (n>=transferred) break;
        std::cout
            << std::setw(4) << i
            << " '" << char(std::isgraph(i)?i : '.') << "'"
            << (++n % 8? ' ':'\n');
    }

甚至 Live On Coliru:

auto buffer = std::make_unique<uint8_t[]>(10'000);
// ...
        boost::asio::buffer(buffer.get(), 10'000),
// ...
    size_t n = 0;
    for (auto it = buffer.get(); it <= buffer.get() + transferred; ++it) {
        std::cout
            << std::setw(4) << static_cast<int>(*it)
            << " '" << char(std::isgraph(*it)?*it : '.') << "'"
            << (++n % 8? ' ':'\n');
    }

如您所见,像这样使用“手动”缓冲区的操作更容易出错,但至少现在您没有内存泄漏。