mirror of
https://github.com/ETLCPP/etl.git
synced 2026-04-30 19:09:10 +08:00
Fixed dereference of state pointer when null.
This commit is contained in:
parent
84dd8ceca3
commit
8710dfc4ff
@ -169,6 +169,18 @@ namespace etl
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// Exception for message received but not started.
|
||||
//***************************************************************************
|
||||
class fsm_not_started : public etl::fsm_exception
|
||||
{
|
||||
public:
|
||||
fsm_not_started(string_type file_name_, numeric_type line_number_)
|
||||
: etl::fsm_exception(ETL_ERROR_TEXT("fsm:not started", ETL_FSM_FILE_ID"F"), file_name_, line_number_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
namespace private_fsm
|
||||
{
|
||||
template <typename T = void>
|
||||
@ -404,31 +416,38 @@ namespace etl
|
||||
//*******************************************
|
||||
void receive(const etl::imessage& message) ETL_OVERRIDE
|
||||
{
|
||||
etl::fsm_state_id_t next_state_id = p_state->process_event(message);
|
||||
|
||||
if (have_changed_state(next_state_id))
|
||||
if (is_started())
|
||||
{
|
||||
ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
|
||||
etl::ifsm_state* p_next_state = state_list[next_state_id];
|
||||
etl::fsm_state_id_t next_state_id = p_state->process_event(message);
|
||||
|
||||
do
|
||||
if (have_changed_state(next_state_id))
|
||||
{
|
||||
ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
|
||||
etl::ifsm_state* p_next_state = state_list[next_state_id];
|
||||
|
||||
do
|
||||
{
|
||||
p_state->on_exit_state();
|
||||
p_state = p_next_state;
|
||||
|
||||
next_state_id = p_state->on_enter_state();
|
||||
|
||||
if (have_changed_state(next_state_id))
|
||||
{
|
||||
ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
|
||||
p_next_state = state_list[next_state_id];
|
||||
}
|
||||
} while (p_next_state != p_state); // Have we changed state again?
|
||||
}
|
||||
else if (is_self_transition(next_state_id))
|
||||
{
|
||||
p_state->on_exit_state();
|
||||
p_state = p_next_state;
|
||||
|
||||
next_state_id = p_state->on_enter_state();
|
||||
|
||||
if (have_changed_state(next_state_id))
|
||||
{
|
||||
ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
|
||||
p_next_state = state_list[next_state_id];
|
||||
}
|
||||
} while (p_next_state != p_state); // Have we changed state again?
|
||||
p_state->on_enter_state();
|
||||
}
|
||||
}
|
||||
else if (is_self_transition(next_state_id))
|
||||
else
|
||||
{
|
||||
p_state->on_exit_state();
|
||||
p_state->on_enter_state();
|
||||
ETL_ASSERT_FAIL(ETL_ERROR(etl::fsm_not_started));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -98,30 +98,37 @@ namespace etl
|
||||
//*******************************************
|
||||
void receive(const etl::imessage& message) ETL_OVERRIDE
|
||||
{
|
||||
etl::fsm_state_id_t next_state_id = p_state->process_event(message);
|
||||
|
||||
if (next_state_id != ifsm_state::No_State_Change)
|
||||
if (is_started())
|
||||
{
|
||||
ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
|
||||
etl::ifsm_state* p_next_state = state_list[next_state_id];
|
||||
etl::fsm_state_id_t next_state_id = p_state->process_event(message);
|
||||
|
||||
// Have we changed state?
|
||||
if (p_next_state != p_state)
|
||||
if (next_state_id != ifsm_state::No_State_Change)
|
||||
{
|
||||
etl::ifsm_state* p_root = common_ancestor(p_state, p_next_state);
|
||||
do_exits(p_root, p_state);
|
||||
ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
|
||||
etl::ifsm_state* p_next_state = state_list[next_state_id];
|
||||
|
||||
p_state = p_next_state;
|
||||
|
||||
next_state_id = do_enters(p_root, p_next_state, true);
|
||||
|
||||
if (next_state_id != ifsm_state::No_State_Change)
|
||||
// Have we changed state?
|
||||
if (p_next_state != p_state)
|
||||
{
|
||||
ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
|
||||
p_state = state_list[next_state_id];
|
||||
etl::ifsm_state* p_root = common_ancestor(p_state, p_next_state);
|
||||
do_exits(p_root, p_state);
|
||||
|
||||
p_state = p_next_state;
|
||||
|
||||
next_state_id = do_enters(p_root, p_next_state, true);
|
||||
|
||||
if (next_state_id != ifsm_state::No_State_Change)
|
||||
{
|
||||
ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
|
||||
p_state = state_list[next_state_id];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ETL_ASSERT_FAIL(ETL_ERROR(etl::fsm_not_started));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@ -672,5 +672,13 @@ namespace
|
||||
CHECK_TRUE(motorControl.exited_state);
|
||||
CHECK_TRUE(motorControl.entered_state);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_fsm_no_states_and_no_start)
|
||||
{
|
||||
MotorControl mc;
|
||||
|
||||
CHECK_THROW(mc.receive(Start()), etl::fsm_not_started);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -978,5 +978,13 @@ namespace
|
||||
bool exitsCorrect = std::equal(motorControl.stateExitHistory.begin(), motorControl.stateExitHistory.end(), expectedExits.begin());
|
||||
CHECK(exitsCorrect);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_fsm_no_states_and_no_start)
|
||||
{
|
||||
MotorControl mc;
|
||||
|
||||
CHECK_THROW(mc.receive(Start()), etl::fsm_not_started);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user