Home > Software design >  Facing double free while implementing a state machine
Facing double free while implementing a state machine

Time:01-24

For a task, I am planning to implement a state machine in C . I am trying to keep a context object which provides following:

  1. a state_ object to keep track of current state
  2. a TransitionTo() method to facilitate transition to new state.

When I wrote the sample implementation and tested it out, I am facing double free error.

I needed help from the community in guiding me on what might be going wrong. Thanks a lot.


#include <iostream>
#include <string>

class State;

/* Context class and method implementation */
class Context
{
    State* state_;
public:
    explicit Context(State* state);
    void TransitionTo(State* newState);
};

Context::Context (State* state): state_ (nullptr) 
{
    this->TransitionTo(state);
}

void Context::TransitionTo(State* newState)
{
    std::cout <<"Requesting state transition to " << newState->stateName<<"\n";
    std::string previous_state_name = "None";
    if (this->state_ != nullptr)
    {
        previous_state_name = this->state_->stateName;
        delete this->state_;
    }
    this->state_ = newState;
    std::cout << "State changed from "<< previous_state_name << " to "<< this->state_->stateName << "\n";
    this->state_->set_context(this);
}



/* State class and method implementation */
class State
{
    protected:
        Context* context_;
    public:
        std::string stateName;
        void set_context(Context* newContext);
        virtual ~State();
        
};

State::~State()
{
    std::cout << stateName <<" state deleted \n";
    delete context_ ;
}

void State::set_context(Context *newContext) 
{
    this->context_ = newContext;
}


/* Declaring different states which are derived from State */
class HappyState : public State
{
public:
    HappyState();
};

HappyState::HappyState()
{
    stateName = "Happy";
}

class NeutralState : public State
{
public:
    NeutralState();
};

NeutralState::NeutralState()
{
    stateName = "Neutral";
}

class SadState : public State
{
public:
    SadState();
};

SadState::SadState()
{
    stateName = "Sad";
}

/* Test the implementation */
int main()
{
    Context* ctx  = new Context(( new NeutralState()));
    
    ctx->TransitionTo(new HappyState());
    
    ctx->TransitionTo(new SadState());

    return 0;
}

When I run this code, I am getting following output: Output snapshot

CodePudding user response:

I found the mistake which was indeed a very silly one.

I was deleting the context_ in ~State() which deleted my original context.

CodePudding user response:

I can't quite figure out why you get a double free. But here are some pointers. Use smart_pointers to avoid senarios like this, e.g unique_ptr and shared_ptr. I'd make a getStateName func in State, instead of keeping stateName as public.

  • Related