【发布时间】:2020-10-14 18:59:01
【问题描述】:
我正在尝试在boost::asio::ip::tcp::socket 之上使用boost::asio 提供的std::iostream 的实现。我的代码几乎逐行复制published in Boost Asio's documentation的示例:
#include <iostream>
#include <stdexcept>
#include <boost/asio.hpp>
int main()
{
using boost::asio::ip::tcp;
try
{
boost::asio::io_service io_service;
tcp::endpoint endpoint(tcp::v4(), 8000);
tcp::acceptor acceptor(io_service, endpoint);
for (;;)
{
tcp::iostream stream; // <-- The exception is triggered on this line, on the second loop iteration.
boost::system::error_code error_code;
acceptor.accept(*stream.rdbuf(), error_code);
std::cout << stream.rdbuf() << std::flush;
}
}
catch (std::exception& exception)
{
std::cerr << exception.what() << std::endl;
}
return 0;
}
唯一的区别是我对生成的tcp::iostream 的使用:我将收到的所有内容转发到标准输出。
当我使用 VisualStudio2019/toolset v142 和来自 NuGet boost-vc142 的 Boost 编译此代码时,我在函数中仅在 for 循环的第二次迭代中得到访问冲突异常
template <typename Service>
Service& service_registry::use_service(io_context& owner)
{
execution_context::service::key key;
init_key<Service>(key, 0);
factory_type factory = &service_registry::create<Service, io_context>;
return *static_cast<Service*>(do_use_service(key, factory, &owner));
} // <-- The debugger show the exception was raised on this line
在asio/detail/impl/service_registry.hpp。所以第一次迭代一切都按计划进行,连接被接受,数据显示在标准输出上,一旦stream第二次在堆栈上实例化,异常就会弹出。
我对调试器报告的异常的这个位置的准确性没有很高的信心。由于某种原因,堆栈接缝被弄乱并且只显示一帧。
如果stream 的声明移出循环,则不会再引发异常,但我需要在循环结束时使用stream.close(),否则除了来自第一个客户端的连接。
基本上,只要我尝试实例化多个boost::asio::tcp::iostream(不一定同时),就会引发异常。
我在 linux 下尝试了完全相同的代码(Arch linux,最新版本的 g++,相同版本的 Boost),一切正常。
我可以通过不使用iostreams 来解决这个问题,但我的想法是将在 tcp 套接字上接收到的数据提供给只接受 std::iostream 实现的解析器,因此我仍然需要包装 asio std::iostream 的自制(平庸)实现中的 tcp 套接字。
如果我在某处遗漏了重要的#define 或其他任何东西,是否有人知道此设置有什么问题?
更新:
随后的调查表明,发生访问冲突的唯一情况是从 Visual Studio 中运行可执行文件时(通常从菜单调试 -> 开始调试)。
构建过程似乎没有效果(直接调用cl.exe,使用MSBuild,使用devenv.exe)。
此外,如果可执行文件是从命令提示符运行的,然后才附加调试器,则不会发生访问冲突。
此时,问题很可能与代码本身无关。
【问题讨论】:
-
真实代码是
tcp::socket;吗?那有什么作用? -
是的,
tcp::socket;是一个有效的语句,但它什么也不做(它是一种解析为boost::asio::basic_stream_socket<boost::asio::ip::tcp>的类型)。为了清楚起见,我编辑了问题以将其删除。 -
我从不怀疑这是一个有效的声明。我什至设法在 Windows 上进行了测试,并发布了我的发现。 [即使这样,我也可以确认虚假线路没有影响。]
标签: sockets visual-c++ boost iostream asio