2016-10-22 2 views
1

부스트 스테이트 머신을 사용하려고하는데 무한 루프로 머신을 돌릴 때 세그멘테이션 폴트가 발생했습니다. 기본적으로 I는 과급 상태 머신 펑 예와 같은 예는 아래 가지고부스트 메타 상태 머신 무한 루프 세그 폴트

enter image description here

유일한 차이점은 지금 "합니다 Event1"를 트리거 따라서 루프를 생성 최대한 빨리 State4 입력으로 발생하기 때문이다. 이 작업은 수천 번 반복되지만 그 다음에는 오류가 발생합니다. 어떤 종류의 UML 규칙을 위반하고 스택을 오버플로합니까? 기본적으로 하나의 블로킹 이벤트 만 있고 다른 모든 상태를 자동으로 트리거 한 다음 State4에서 종료합니다 (실제로는 네트워크에서 메시지를 기다리는 블로킹 호출 일 것입니다). 스택을 날려 버리지 않으려면 어떻게 메타 상태 머신을 사용하여 이것을 올바르게 구현할 수 있습니까?

여기 내 문제의 원인이되는 소스 코드를 포함 시켰습니다
UPDATE : http://pastebin.com/fu6rzF0Q

이 기본적으로 다음과 같은 변화를 제외하고 펑 프론트 엔드의 예는 다음과 같습니다

추가를 "차단"통화 기능 차단 :

struct BlockingCall { 
    template <class EVT, class FSM, class SourceState, class TargetState> 
    void operator()(EVT const &, FSM &, SourceState &, TargetState &) { 
     std::cout << "my_machine::Waiting for a thing to happen..." << std::endl; 
     // Pretend I'm actually waiting for something 
     std::this_thread::sleep_for(std::chrono::milliseconds(100)); 
     std::cout << "my_machine::OMG the the thing happened!" << std::endl; 
    } 
    }; 

그리고 마지막으로 트란 sition 테이블 :

더 이상 State1 정에 State4에서 이동 트리거해야하는 경우가 있음을
 struct transition_table : mpl::vector< 
     // Start  Event   Next  Action    Guard 
     // +---------+-------------+---------+---------------------+----------------------+ 
     Row < State1 , none  , State2            >, 
     Row < State2 , none  , State3 , State2ToState3        >, 
     Row < State3 , none  , State4 , none    , always_false   >, 
     // +---------+-------------+---------+---------------------+----------------------+ 
     Row < State3 , none  , State4 , State3ToState4  , always_true   >, 
     Row < State4 , none  , State1 , BlockingCall        > 
     // +---------+-------------+---------+---------------------+----------------------+ 
    > {}; 

알 수 있습니다. 이 코드는 의심의 여지없이 seg 오류를 일으키며 스택 추적은 1000 초 길이입니다.

내가 기다리는 시간에 관계없이 나는 항상 결국 오류가 있음을 알아야합니다. 나는 수면을 1 - 100로 바꾸면서 놀았으며 결국 죽을 것입니다. 단일 루프가 완료되면 스택을 언 롤링 할 방법이 필요합니다. 2

UPDATE 그래서 나는 무한 루프에서 이벤트를 트리거 할 때 내가 독방 감금 잘못을하지 않는 것을 발견했다.

struct transition_table : mpl::vector< 
     // Start  Event   Next  Action    Guard 
     // +---------+-------------+---------+---------------------+----------------------+ 
     Row < State1 , none  , State2            >, 
     Row < State2 , none  , State3 , State2ToState3        >, 
     Row < State3 , none  , State4 , none    , always_false   >, 
     // +---------+-------------+---------+---------------------+----------------------+ 
     Row < State3 , none  , State4 , State3ToState4  , always_true   >, 
     Row < State4 , event1  , State1 , none          > 
     // +---------+-------------+---------+---------------------+----------------------+ 
    > {}; 

가 그럼 난 다음에 메인 프로그램을 변경 :

먼저 내가 원래 예제로 다시 전환 테이블을 설정 : 여기에 내가 무슨 짓을

void test() { 
    my_machine p; 

    // needed to start the highest-level SM. This will call on_entry and mark the 
    // start of the SM 
    // in this case it will also immediately trigger all anonymous transitions 
    p.start(); 
    // this event will bring us back to the initial state and thus, a new "loop" 
    // will be started 
    while (true) { 
    p.process_event(event1()); 
    } 
} 

그리고 지금은이 전속력으로 (잠을 자지 않고) 달렸고 나는 세그 폴트하지 않았다. 이것을 토대로 상태 머신을 시작하고 내부 이벤트를 실행하고 처리하는 방법이없는 것 같습니다. 맞습니까? 나는 적어도 외부에서도 어떤 과정을 일으켜야 만 하는가?

UPDATE 3 궁극적으로 나의 목표는 다음 그림과 같이 구현하는 것입니다 : 이

내 의도는 상태 머신을 시작하는 것입니다, 그리고 그것은 단순히 더 이상 개입하지 않고 수신 메시지를 기다립니다 .

+0

[MCVE] –

+0

@ m.s를 게시해야합니다. 귀하의 추천으로 내 질문을 업데이트했습니다. – user985030

+0

특정 도구에서 Wesson을 구현하는 방법에 대해 답변을 드릴 수는 없지만 직접 언급 만 할 것입니다. UML 관점에서 볼 때 립은 유한 한 가치가 없다. 사실 아주 자주 주 기계가 무한대로 진행되지만 대개 하나 이상의 주정부가 최종판으로 간주됩니다. 그러나 실제 구현으로 갈 때 많은 문제가 발생할 수 있으며 무한 루프는 이러한 문제를 드러내는 경향이 있습니다. 툴의 한계로 인해 절대적으로 유효한 UML 상태 머신이 당신이 선택한 툴로 구현 될 수 없을 수도 있습니다. – Ister

답변

0

fsm.process_event(e1)을 action/guards/entry/exit 문 내부에 호출하면 상태 시스템에 내부 루프가있을 수 없다는 결론을 얻었습니다. 문제는 스택을 오버플로 할 때까지 스택에서 더 많은 정보를 전달한다는 것입니다. 익명 전환이 상태 시스템에 무한 루프를 작성하는 경우에도 마찬가지입니다. 그래서 결론적으로 루프를 시작하려면 최소한 ONE 외부 이벤트가 있어야합니다. 따라서 다음 코드는 지금까지 찾은 최고의 솔루션입니다.

void test() { 
    my_machine p; 
    p.start(); 
    // Must have at least 1 triggering external event to not overflow the stack 
    while (true) { 
    p.process_event(event1()); 
    } 
}