在asio reactor中使用auto与typedef for lambda

时间:2015-04-17 08:05:58

标签: sockets c++11 lambda boost-asio

我有一些像这样的代码:

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。

干杯 本

1 个答案:

答案 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的本质是任何事情都可能发生,这就解释了为什么你会看到不同的行为。