boost asio错误类别为空

boost asio error category is null

本文关键字:错误类别 asio boost      更新时间:2023-10-16

在我的基于asio的应用程序中,我在错误处理方面遇到了问题。我将asio单线程/单io_service与async_read/async_write函数一起使用,当在完成处理程序中传递给我的错误代码不为null时,对其.message()方法的任何调用都会导致segfault,因为错误类别指针指向null。但是,实际值总是正确的。

奇怪的是,我无法在测试应用程序中重现这一点。这基本上就是我正在做的,但如果出现错误,在这里调用message()可以正常工作:

void do_write(std::shared_ptr<std::vector<unsigned char>> , std::shared_ptr<boost::asio::ip::tcp::socket> );
void do_read(std::shared_ptr<std::vector<unsigned char>> buf, std::shared_ptr<boost::asio::ip::tcp::socket> sock)
{
boost::asio::async_read(*sock, boost::asio::buffer(*buf), boost::asio::transfer_exactly(100000),
[sock, buf](const boost::system::error_code& ec, std::size_t bytes)
{
std::cout << "readn";
if (ec) {
std::cout << ec.message() << std::flush;
} else {
do_write(buf, sock);
}
});
}
void do_write(std::shared_ptr<std::vector<unsigned char>> buf, std::shared_ptr<boost::asio::ip::tcp::socket> sock)
{
boost::asio::async_write(*sock, boost::asio::buffer(*buf), [sock, buf](const boost::system::error_code& ec, std::size_t bytes)
{
std::cout << "writen";
if (ec) {
std::cout << ec.message() << std::flush;
} else {
do_read(buf, sock);
}
});
}
int main()
{
auto buf = std::make_shared<std::vector<unsigned char>>(100000);
unsigned short port = 1113;
boost::asio::io_service ios;
boost::asio::ip::tcp::acceptor acptr {ios, boost::asio::ip::tcp::endpoint{boost::asio::ip::tcp::v4(), port}};
auto socket = std::make_shared<boost::asio::ip::tcp::socket>(acptr.get_io_service());
acptr.async_accept(*socket, [socket, buf](const boost::system::error_code& ec)
{
do_read(buf, socket);
});
ios.run();
}

我不认为这是我的应用程序寿命的问题,AddressSanitizer没有发现任何潜在的错误,我可以毫无问题地转移数百兆字节的数据。此外,如果我只是取消注释对message()的调用,服务器将继续正常运行并正确处理新连接。无论如何,以下是崩溃发生时的调用堆栈:

https://gist.github.com/mariusherzog/82f24caf9eea4d94946706aa8c025ef1类别从第11帧向上指向零。

我使用linux与clang 3.9.1和gcc 5.4.0 的boost 1.62

我现在唯一能想到的是,一段代码作为构建全局静态数据的一部分进行初始化。如果它当时获取了一个类别引用,并且有多个翻译单元,那么该类别实例可能还没有构建。

这种情况被亲切地称为静态初始化顺序Fiasco。


除此之外,人们会想到相反的情况(全局类别已被破坏)。这似乎不太可能,因为1。你会意识到它发生在关机2。在这种情况下,引用通常不会变为null,尽管实现可能会