我有一些像这样的代码:
typedef std::function<void (void)> const& basic_callback_t;
void Receive::async_basic(fragmenting_socket& socket, const ID id, basic_callback_t fn)
{
int buffer[1024];
socket.async_receive(buffer, sizeof(buffer), [&](const boost::system::error_code& ec, size_t bytes)
{
....
if (fn)
{
fn();
} else
{
THROW("async_receive callback: Could not call fn()");
}
});
}
且socket.async_receive()
正在调用boost::asio::ip::udp::socket::async_receive_from()
我使用以下代码调用async_basic()
:
boost::asio::io_service m_service;
fragmenting_socket m_camera_socket { m_service, 0, 0 };
std::thread service_thread([&] { m_service.run(); });
bool finished = false;
// NOTE: this is weird, when I correctly define f as basic_callback_t, it works.
// when I use "auto f" or keep the lambda anonymous, then it gets invalidated inside the asio reactor
protocol::basic_callback_t f = [&finished] ()
{
finished = true;
};
protocol::Receive::async_basic(m_camera_socket, protocol::ID::QUERY, f);
上面的代码似乎工作正常,f
被调用并且finish被设置为true。但是,如果我将匿名lambda传递给async_basic
或将f
声明为
auto f = [&] () ....
然后asio reactor将fn
内的async_receive
视为超出范围,并调用THROW()
语句。有谁知道为什么会发生这种情况?我真的很困惑为什么明确地声明f
作为protocol::basic_callback_t
起作用并将其声明为auto
不起作用。在这两种情况下,仿函数都放在堆栈上,并且应该在m_service
正在运行的线程中超出范围。
我正在用g ++ 4.8.2编译-std = c ++ 11标志和-fPIC。
干杯 本
答案 0 :(得分:2)
在两种变体中,您都有Undefined Behaviour
void Receive::async_basic(fragmenting_socket& socket, const ID id, basic_callback_t fn)
{
int buffer[1024];
socket.async_receive(buffer, sizeof(buffer), [&](const boost::system::error_code& ec, size_t bytes)
{
if (fn) {
fn();
} else {
THROW("async_receive callback: Could not call fn()");
}
});
对async_receive
的调用通过引用捕获fn
。但是,只要async_basic
返回,引用就会变为无效。
事实上同样适用于buffer[]
:buffer
超出了范围,因此您有async_receive
写入的未定义行为。< / p>
UB的本质是任何事情都可能发生,这就解释了为什么你会看到不同的行为。