lambda reference capturing leads to unexpected behaviour

34 views Asked by At

So I was trying to get my feet wet with asio library. But am baffled by the following lambda capture mystery.

#include <iostream>
#include <asio/include/asio.hpp>

void handler1( const asio::error_code& ec, asio::steady_timer& t, int count ) {
    if( count < 5  ) {
        std::cout << "I have waited " << count << " seconds\n";
        t.expires_at( t.expiry() + asio::chrono::seconds( 1 ) );
        // auto next_count = count + 1;
        t.async_wait( [&t, &count]( const asio::error_code& ec ) {
            handler1( ec, t, count + 1 );
        });
    }
}

int main(int argc, char *argv[])
{
    asio::io_context io_context;
    asio::steady_timer t ( io_context, asio::chrono::seconds( 1 ) );
    t.async_wait( [&t]( const asio::error_code& ec ) {
                handler1( ec, t, 0 );
            }
     );

    io_context.run();
    return 0;
}

Problem happens on the &count lambda capture in the handler1 function. This code will produce the following on my Mac:

(Apple Clang++ 15.0.0)

I have waited 0 seconds
I have waited 2 seconds
I have waited 2 seconds
... ...

(g++ 13.2.0)

I have waited 0 seconds
I have waited 1 seconds
I have waited 1 seconds
... ...

If the &count capture is changed to count, which is capture by copy, it produces expected behavior (g++ 13.2.0)

I have waited 0 seconds
I have waited 1 seconds
I have waited 2 seconds
I have waited 3 seconds
... ...

So what is going on. I am pretty sure the function handler1 captures count by copy, so I don't think there will be any difference between capturing the count by reference or value in the lambda capture.

0

There are 0 answers