C ++:Boost io_context / strand wrap导致shared_ptr上的段错误

问题描述

有人可以帮助我理解为什么我从代码片段中得到以下结果吗?如果将lambda函数更改为至少包含1个参数:我两次获得了“ valid ptr”输出。这是在我的代码中发生的段错误崩溃中发现的。

Output:
  valid ptr
  nullptr

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

auto getWrapper(boost::asio::io_context& ioContext) 
{
    auto sharedPtr = std::make_shared<int>(0);
    return ioContext.wrap( [sharedPtr](){ 
                                          if(sharedPtr == nullptr) 
                                            std::cout << "nullptr\n";
                                          else
                                            std::cout << "valid ptr\n";
                                         });
}

int main()
{
    boost::asio::io_context ioContext;
    auto wrapper = getWrapper(ioContext);
    wrapper();
    wrapper();
    ioContext.run();
}

解决方法

首先,您必须实际使用绞线,并且不赞成使用io_context::wrap。 所以让我们写

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

auto getScheduleWrapper(boost::asio::io_context::strand& strand)
{
    auto sharedPtr = std::make_shared<int>(0);
    return [sharedPtr,&strand] () {
    boost::asio::post(strand.context(),boost::asio::bind_executor(strand,[sharedPtr] (){
                          if(sharedPtr == nullptr)
                              std::cout << "nullptr\n";
                          else
                              std::cout << "valid ptr\n";
                      }));
        };
}

int main()
{
    boost::asio::io_context ioContext;
    boost::asio::io_context::strand strand{ioContext};
    auto scheduleWrapper = getScheduleWrapper(strand);
    scheduleWrapper();
    scheduleWrapper();

    ioContext.run();
}

这将输出

valid ptr
valid ptr

符合预期。但请注意:线程并不能保证计划的任务将运行一次,而实际上您是在计划两次。它们是“唯一的”保证在该分支上一次只能运行一个任务,并且将按照最初计划的顺序运行。