代码之家  ›  专栏  ›  技术社区  ›  Michał Hanusek

升压.SML-违反内存保护/分段错误

  •  0
  • Michał Hanusek  · 技术社区  · 6 年前

    程序返回“ 分段故障(堆芯倾倒) ". 怎么了?

    该实现基于示例-' '表单文档升压.SML:

    http://boost-experimental.github.io/sml/examples/index.html#nested

    性虐待 服务器 . 这个 服务器 用于切换SM中的状态。

    #include <boost/sml.hpp>
    #include <iostream>
    namespace sml = boost::sml;
    using namespace std;
    
    template <class = class Dummy>
    class Server
    {
    struct pollEvent{};
    struct msgRcdEvent{};
    
    class States
    {
    public:
     States(Server *server): _server(server){}
    
    auto operator()() const noexcept
    {
      auto msgRcdAction = [this] {
      std::cout << "HB server -> msgRcdAction " << std::endl;
     _server->recvMsg();
    };
    
    auto pollAction = [this] {
     std::cout << "HB server -> pollAction " << std::endl;
      _server->poll();
    };
    
    using namespace sml;
    
    return make_transition_table(
     *"idle"_s + event<pollEvent> / pollAction    = "Poll"_s,
     "Poll"_s + event<msgRcdEvent> / msgRcdAction = "RcdMsg"_s,
     "RcdMsg"_s + event<pollEvent> / pollAction   = "Poll"_s
    );
    }
    private:
     Server *_server{nullptr};
    };
    
    public:
     Server()
     {
      _states = new States(this);
      _sm     = new sml::sm<States>(*_states);
     }
    
     void process(){_sm->process_event(pollEvent{});}
     void poll(){_sm->process_event(msgRcdEvent{});}
     void recvMsg(){_sm->process_event(pollEvent{});}
    
    private:
     States *_states{nullptr};
     sml::sm<States> *_sm{nullptr};
    };
    
    int main()
    {
     Server<> s{};
     s.process();
     return 0;
    }
    
    1 回复  |  直到 6 年前
        1
  •  0
  •   Takatoshi Kondo    6 年前

    分段错误是由堆栈溢出引起的。因为 _sm->process_event(...) 递归调用。函数立即处理事件。

    为了避免这种情况的发生,我们需要一种排队事件机制,而不是立即处理事件。

    sml提供。

    这是密码。请参阅评论1至3。

    #include <boost/sml.hpp>
    #include <iostream>
    #include <queue>
    
    namespace sml = boost::sml;
    using namespace std;
    
    template <class = class Dummy>
    class Server
    {
        struct pollEvent{};
        struct msgRcdEvent{};
    
        class States
        {
        public:
            States(Server *server): _server(server){}
    
            auto operator()() const noexcept
            {
                auto msgRcdAction =
                    // 2. Add parameters to lambda expression
                    //    The second parameter is process callable object that is from
                    //    action. The template argument `pollEvent` is the event you want
                    //    to pass to the `process`.
                    //    You can write multiple template arguments.
                    //    e.g.) sml::back::process<pollEvent, msgRcdEvent>
                    [this] (auto const& /*ev*/, sml::back::process<pollEvent> process) {
                        std::cout << "HB server -> msgRcdAction " << std::endl;
                        _server->recvMsg(process);
                    };
    
                auto pollAction =
                    [this] (auto const& /*ev*/, sml::back::process<msgRcdEvent> process) {
                        std::cout << "HB server -> pollAction " << std::endl;
                        _server->poll(process);
                    };
    
                using namespace sml;
    
                return make_transition_table(
                    *"idle"_s + event<pollEvent> / pollAction    = "Poll"_s,
                    "Poll"_s + event<msgRcdEvent> / msgRcdAction = "RcdMsg"_s,
                    "RcdMsg"_s + event<pollEvent> / pollAction   = "Poll"_s
                );
            }
        private:
            Server *_server{nullptr};
        };
    
    public:
        Server()
        {
            _states = new States(this);
            _sm     = new sml::sm<States, sml::process_queue<std::queue>>(*_states);
        }
    
        void process1(){_sm->process_event(pollEvent{});}
    
        // 3. Invoke process callable object
        template <typename Process>
        void poll(Process p){ p(msgRcdEvent{});}
        template <typename Process>
        void recvMsg(Process p){ p(pollEvent{});}
    
    private:
        States *_states{nullptr};
    
        // 1. Add `sml::process_queue<std::queue>` template argument to `sml::sm`.
        sml::sm<States, sml::process_queue<std::queue>> *_sm{nullptr};
    };
    
    int main()
    {
        Server<> s{};
        s.process1();
        return 0;
    }
    

    sml::back::process<pollEvent> (注释2)是一个可调用(类似函数)的对象,正在对事件进行排队。你可以叫它代替 (评论3)。 队列被设置为的模板参数 sm