首页 > 解决方案 > 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();
}

标签: c++boostsegmentation-faultshared-ptr

解决方案


首先,您必须实际使用 strand 并且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

正如预期的那样。但请注意:strands 并不保证计划任务会运行一次,而实际上您是在计划两次。它们“仅”保证在该链上一次只运行一个任务,并且它们将按照最初计划的顺序运行。


推荐阅读