首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >调用boost resolve::async_resolve时捕获值的错误值

调用boost resolve::async_resolve时捕获值的错误值
EN

Stack Overflow用户
提问于 2016-11-24 17:02:55
回答 1查看 107关注 0票数 2

我无法理解下面代码的行为。定义符号BUG时,变量this的第三次打印是错误的。

我认为resolver::async_resolve方法中有些东西破坏了代码。我想了解什么:-)

谢谢

代码语言:javascript
复制
#include <boost/asio.hpp>
#include <iostream>

using namespace std;

template <typename F>
#ifdef BUG
void Connect( boost::asio::ip::tcp::resolver& resolver, F Connected )
#else
void Connect( boost::asio::ip::tcp::resolver& resolver, const F& Connected )
#endif
{
    resolver.async_resolve(
        boost::asio::ip::tcp::resolver::query{ "localhost", "8088" },
        [&Connected]( const boost::system::error_code& ec, boost::asio::ip::tcp::resolver::iterator i )
        {
            Connected();
        }
    );
}

struct Test
{
    void Start()
    {
        cout << "this1 " << hex << this << dec << endl;
        auto handler = [this]()
        {
            cout << "this2 " << hex << this << dec << endl;
            boost::asio::ip::tcp::resolver resolver{ ios };
            Connect( resolver, [this]()
                {
                    cout << "this3 " << hex << this << dec << std::endl;
                }
            );
        };
        handler();
        ios.run();
    }

    boost::asio::io_service ios;
};

int main()
{
    Test t;
    t.Start();
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-11-24 21:32:52

您的错误不是通过值传递给Connect而不是通过const引用传递,而是由于调用对lambda的悬空引用而导致的未定义行为。

这是因为在传递给async_resolve的lambda中通过引用捕获async_resolve

代码语言:javascript
复制
resolver.async_resolve(
    boost::asio::ip::tcp::resolver::query{ "localhost", "8088" },
    [&Connected]( const boost::system::error_code& ec, boost::asio::ip::tcp::resolver::iterator i )
    {
        Connected(); // Connected is captured by reference
    }
);

当调用Connected()时,它已经从堆栈中弹出并销毁。

代码语言:javascript
复制
void Start()
{
    cout << "this1 " << hex << this << dec << endl;
    auto handler = [this]()
    {
        cout << "this2 " << hex << this << dec << endl;
        boost::asio::ip::tcp::resolver resolver{ ios };
        Connect( resolver, [this]()
            {
                cout << "this3 " << hex << this << dec << std::endl;
            }
        );
    };
    handler(); // after this function returns Connected will be destructed
    ios.run(); // the thread is blocked in ios.run until the resolve returns
}
  • handler()的调用在堆栈上创建"Connected“lambda并将其传递给Connect,后者将创建一个lambda ,该通过引用捕获,并启动一个异步操作。
  • 然后handler()返回,从堆栈中弹出"Connected“,销毁它。
  • ios.run()在等待async_resolve返回时阻止Test::Start()返回。
  • async_resolve完成了,并调用了它的lambda,作为回报,它调用了已被销毁的Connected()

您可以通过捕获 by value来解决这一问题。

代码语言:javascript
复制
void Connect( boost::asio::ip::tcp::resolver& resolver, F Connected )
{
    resolver.async_resolve(
        boost::asio::ip::tcp::resolver::query{ "localhost", "8088" },
        [Connected]( const boost::system::error_code& ec, boost::asio::ip::tcp::resolver::iterator i )
        {
            Connected();
        }
    );
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40791668

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档