C++ c++;保存绑定对象并在asio后使用它

C++ c++;保存绑定对象并在asio后使用它,c++,c++11,boost-asio,std-function,C++,C++11,Boost Asio,Std Function,我试图保存bind to std:function的结果,然后将其作为参数传递给另一个函数,并将其存储为数据成员。然后我使用asio async_wait,但是当我从等待中返回并尝试操作我保存的函数时,我得到了分段错误。知道为什么吗 #include <memory> #include <iostream> #include <asio/io_service.hpp> #include <functional> #include <asio/

我试图保存bind to std:function的结果,然后将其作为参数传递给另一个函数,并将其存储为数据成员。然后我使用asio async_wait,但是当我从等待中返回并尝试操作我保存的函数时,我得到了分段错误。知道为什么吗

#include <memory>
#include <iostream>
#include <asio/io_service.hpp>
#include <functional>
#include <asio/deadline_timer.hpp>

using namespace std;

typedef std::function<void (const std::error_code& error)> TM_callback;

class Timer {
public:
    Timer(asio::io_service& io_service) :_timer(io_service) {}

    void start(TM_callback cb) {
        _cb = cb;
      _timer.expires_from_now(boost::posix_time::milliseconds(1000));
        TM_callback timeoutFunc = std::bind(&Timer::onTimeout, this, std::placeholders::_1);
        _timer.async_wait(timeoutFunc);
    }

private:
    void onTimeout(const std::error_code& error) {
        (_cb)(error); // <-- here i get segmentation fault
    }

    TM_callback _cb;
    asio::deadline_timer _timer;
};

class COL {
public:
    COL(asio::io_service& io_service): _inTimer(io_service){}
void startInTimer() {
    TM_callback cb = std::bind(&COL::onInTimeout, this, std::placeholders::_1);
    _inTimer.start(cb);
}

private:
void onInTimeout(const std::error_code& error) {cout<<error.message();}
    Timer _inTimer;
};

int main()
{
    asio::io_service io_service;
    COL col(io_service);
    col.startInTimer();

    return 0;
}
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
typedef std::函数TM_回调;
班级计时器{
公众:
计时器(asio::io_服务和io_服务):_计时器(io_服务){}
无效启动(TM_回调cb){
_cb=cb;
_timer.expires_from_now(boost::posix_time::毫秒(1000));
TM_callback timeoutpunc=std::bind(&Timer::onTimeout,this,std::placeholder::_1);
_timer.async_wait(timeoutpunc);
}
私人:
void onTimeout(const std::error\u code&error){

(_cb)(error);//好的,最有可能的问题是您没有显示的代码。正如您所看到的,@m.s.没有“想象”您的问题。他也忘记了
io_服务::run()

int main() {
    asio::io_service io_service;
    COL col(io_service);
    col.startInTimer();
    io_service.run();
}
还是没问题。

#include <iostream>
#include <boost/bind.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/make_shared.hpp>
#include <boost/asio.hpp>

using namespace std;

typedef std::function<void(const boost::system::error_code &error)> TM_callback;

namespace asio = boost::asio;

class Timer : public boost::enable_shared_from_this<Timer> {
  public:
    Timer(asio::io_service &io_service) : _timer(io_service) {}

    void start(TM_callback cb) {
        _cb = cb;
        _timer.expires_from_now(boost::posix_time::milliseconds(1000));
        TM_callback timeoutFunc = boost::bind(&Timer::onTimeout, shared_from_this(), boost::asio::placeholders::error);
        _timer.async_wait(timeoutFunc);
    }

  private:
    void onTimeout(const boost::system::error_code &error) {
        (_cb)(error);
    }

    TM_callback _cb;
    asio::deadline_timer _timer;
};

class COL : public boost::enable_shared_from_this<COL> {
  public:
    COL(asio::io_service &io_service) : _svc(io_service) {}

    void startInTimer() {
        TM_callback cb = boost::bind(&COL::onInTimeout, shared_from_this(), boost::asio::placeholders::error);

        boost::shared_ptr<Timer> _inTimer = boost::make_shared<Timer>(_svc);
        _inTimer->start(cb);
    }

  private:
    void onInTimeout(const boost::system::error_code &error) { cout << error.message(); }
    asio::io_service& _svc;
};

int main() {
    asio::io_service io_service;
    {
        boost::make_shared<COL>(io_service)->startInTimer();
    }
    io_service.run();
}
在执行完成处理程序之前,
inTimer
不保证有效时,问题开始:

int main() {
    asio::io_service io_service;
    {
        COL col(io_service);
        col.startInTimer();
    }
    io_service.run();
}
现在您有了:

#include <iostream>
#include <boost/bind.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/make_shared.hpp>
#include <boost/asio.hpp>

using namespace std;

typedef std::function<void(const boost::system::error_code &error)> TM_callback;

namespace asio = boost::asio;

class Timer : public boost::enable_shared_from_this<Timer> {
  public:
    Timer(asio::io_service &io_service) : _timer(io_service) {}

    void start(TM_callback cb) {
        _cb = cb;
        _timer.expires_from_now(boost::posix_time::milliseconds(1000));
        TM_callback timeoutFunc = boost::bind(&Timer::onTimeout, shared_from_this(), boost::asio::placeholders::error);
        _timer.async_wait(timeoutFunc);
    }

  private:
    void onTimeout(const boost::system::error_code &error) {
        (_cb)(error);
    }

    TM_callback _cb;
    asio::deadline_timer _timer;
};

class COL : public boost::enable_shared_from_this<COL> {
  public:
    COL(asio::io_service &io_service) : _svc(io_service) {}

    void startInTimer() {
        TM_callback cb = boost::bind(&COL::onInTimeout, shared_from_this(), boost::asio::placeholders::error);

        boost::shared_ptr<Timer> _inTimer = boost::make_shared<Timer>(_svc);
        _inTimer->start(cb);
    }

  private:
    void onInTimeout(const boost::system::error_code &error) { cout << error.message(); }
    asio::io_service& _svc;
};

int main() {
    asio::io_service io_service;
    {
        boost::make_shared<COL>(io_service)->startInTimer();
    }
    io_service.run();
}
解决方案 最简单的解决方案是使
(那是什么?)对象寿命足够长。更结构化/惯用的方法是让
绑定
使
计时器
对象保持活动状态,例如使用
共享的ptr

#include <iostream>
#include <boost/bind.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/make_shared.hpp>
#include <boost/asio.hpp>

using namespace std;

typedef std::function<void(const boost::system::error_code &error)> TM_callback;

namespace asio = boost::asio;

class Timer : public boost::enable_shared_from_this<Timer> {
  public:
    Timer(asio::io_service &io_service) : _timer(io_service) {}

    void start(TM_callback cb) {
        _cb = cb;
        _timer.expires_from_now(boost::posix_time::milliseconds(1000));
        TM_callback timeoutFunc = boost::bind(&Timer::onTimeout, shared_from_this(), boost::asio::placeholders::error);
        _timer.async_wait(timeoutFunc);
    }

  private:
    void onTimeout(const boost::system::error_code &error) {
        (_cb)(error);
    }

    TM_callback _cb;
    asio::deadline_timer _timer;
};

class COL : public boost::enable_shared_from_this<COL> {
  public:
    COL(asio::io_service &io_service) : _svc(io_service) {}

    void startInTimer() {
        TM_callback cb = boost::bind(&COL::onInTimeout, shared_from_this(), boost::asio::placeholders::error);

        boost::shared_ptr<Timer> _inTimer = boost::make_shared<Timer>(_svc);
        _inTimer->start(cb);
    }

  private:
    void onInTimeout(const boost::system::error_code &error) { cout << error.message(); }
    asio::io_service& _svc;
};

int main() {
    asio::io_service io_service;
    {
        boost::make_shared<COL>(io_service)->startInTimer();
    }
    io_service.run();
}
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
typedef std::函数TM_回调;
名称空间asio=boost::asio;
类计时器:public boost::从\u启用\u共享\u{
公众:
计时器(asio::io_服务和io_服务):_计时器(io_服务){}
无效启动(TM_回调cb){
_cb=cb;
_timer.expires_from_now(boost::posix_time::毫秒(1000));
TM_callback timeoutpunc=boost::bind(&Timer::onTimeout,shared_from_this(),boost::asio::placeholders::error);
_timer.async_wait(timeoutpunc);
}
私人:
void onTimeout(const boost::system::error\u代码和错误){
(_cb)(错误);
}
TM_callback_cb;
asio::截止时间计时器;
};
类COL:public boost::从\u中启用\u共享\u{
公众:
COL(asio::io_服务和io_服务):\u svc(io_服务){}
void startInTimer(){
TM_callback cb=boost::bind(&COL::onInTimeout,shared_from_this(),boost::asio::placeholders::error);
boost::shared\u ptr\u inTimer=boost::make\u shared(\u svc);
_初始化->启动(cb);
}
私人:
void onInTimeout(const boost::system::error_code&error){cout startInTimer();
}
io_service.run();
}

请注意,这也巧妙地解决了一个问题,即在给定时间内不能有多个计时器(安排一个新计时器将取消挂起的计时器).

你需要发布一个我不确定它如何能比我发布的版本更精简,但它还不完整;你可以发布代码,有人可以复制、粘贴和编译。我已经更新了它以完成代码,请帮助,谢谢Hanks@m.s。我可以从那里猜到问题,但你完全正确。这让人恼火当人们故意忽略问题代码时。谢谢,问题解决了!问题确实是其他代码删除了COL对象(COL是内部逻辑代码的上下文).关于您现在分配_initimer的注意事项,我不确定它是否最适合我的设计。我想通过简单地调用_initimer->cancel()来取消计时器,因此我不确定在这种情况下,计时器之间是否存在竞争条件。如果我在取消时删除计时器,并在启动时分配一个新的计时器,是否会导致内存碎片?而且分配本身也很耗时。