简体   繁体   English

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

[英]Boost.SML - Violation of memory protection/Segmentation fault

The program returns " Segmentation fault (core dumped) ". 程序返回“ 分段错误(核心已转储) ”。 What is wrong? 怎么了?

The implementation is based on the example - ' Nested ' form documentation BOOST.SML: 该实现基于示例-“ 嵌套 ”表单文档BOOST.SML:

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

SM is used to call methods from the Server . SM用于从服务器调用方法。 The Server is used to switch states in the SM. 服务器用于切换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;
}

Segmentation fault is caused by stack overflow. 分段错误是由堆栈溢出引起的。 Because _sm->process_event(...) is called recursively. 因为_sm->process_event(...)是递归调用的。 The function processes the event immediately. 该函数立即处理事件。

In order to avoid it, we need something that queuing event mechanism instead of process the event immediately. 为了避免这种情况,我们需要对事件机制进行排队而不是立即处理事件。

sml provides it. sml提供了它。

Here is the code. 这是代码。 Please see comments 1 to 3. 请参阅评论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> (comment 2) is a callable (function like) object that is queuing the event. sml::back::process<pollEvent> (注释2)是可排队的(类似于函数的)对象,正在排队该事件。 You can call it instead of _sm->process_event(...) (comment 3). 您可以调用它而不是_sm->process_event(...) (注释3)。 The queue is set as the template argument of sm (comment 1). 队列被设置为sm的模板参数(注释1)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM