我对套接字通信感兴趣,使用boost库。 当我从服务器收到一条消息并尝试将其转换为atomic<;uint8_t>*
时,它会给我一个错误,即'static_cast':无法将“const void*”转换为“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,不要使用new
,malloc
(或delete
或free
)。
具体地说,我看到了指向套接字的指针,指向所有东西的指针。 如果使分配工作,则会泄漏用new
分配的整个缓冲区。
这里有一个更简单的方法,削减双缓冲(streambuf
):
uint8_t buffer[10000];
auto transferred = boost::asio::read(
sock,
boost::asio::buffer(buffer),
boost::asio::transfer_all(),
ec);
现在,成功后,transferred
字节将已经位于您分配的缓冲区中。 更简单的是使用
std::vector<uint8_t> buffer(10000);
因为这样你就可以简单地
buffer.resize(transferred);
住在科里鲁
#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 '.'
std::vector
已经执行堆分配。 我你坚持原始C数组语义,考虑活在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');
}
甚至住在科里鲁:
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');
}
正如您所看到的那样,使用“手动”缓冲区的操作更容易出错,但至少现在您不会出现内存泄漏。