Alex
Alex

Reputation: 2299

Problems when freeing memory when I have undo/redo

I'm working on a project for a class where we are supposed to implement basic functionality for a text editor, including undo and redo. I currently have my undo/redo functions working correctly, the only problem is, is that I'm getting a valgrind error when trying to free the memory from a Command object that tells us what to execute.

This Command object is part of a struct within a namespace like so:

struct UserInteraction
{
    UserInteractionType type;
    Command* command;
};

Currently, I store each command that the user issues in a std::vector of type <UserInteraction> called undoStack. I also have a redoStack of the same type which is also a std::vector. Storing each command looks like this:

    else if (interaction.type == UserInteractionType::command) // COMMAND
    {
        try
        {
            interaction.command->execute(editor);
            commandInteraction = true;
            undoStack.push_back(interaction);
            view.clearErrorMessage();
        }
        catch (EditorException& e)
        {
            delete interaction.command;
            view.showErrorMessage(e.getReason());
        }
        view.refresh();
    } // end if-else

I need to deallocate each UserInteraction that was pushed into the vector, when the user presses ctrl+x (which exits the program). Otherwise, any command I issue gives me a error like this:

4 bytes in 1 blocks are definitely lost in loss record 2 of 38

Where each command entered increases the amount of bytes by lost by 4.

I figured I just needed to deallocate all the memory used by each vector within the quit command, but all the current solutions that people use seem to still give me memory leaks. Here are two versions of my quit method (both of which still give me memory leaks):

First try:

    if (interaction.type == UserInteractionType::quit)
    {
        clear undo
        std::vector<UserInteraction>().swap(undoStack);
        clear redo
        std::vector<UserInteraction>().swap(redoStack);
        break;
    }

And my second try at deallocating memory:

    if (interaction.type == UserInteractionType::quit)
    {
        undoStack.clear();
        undoStack.shrink_to_fit();
        redoStack.clear();
        redoStack.shrink_to_fit();
        break;
    }

So how can I actually deallocate everything in both vectors?

Upvotes: 1

Views: 219

Answers (1)

MikeMB
MikeMB

Reputation: 21156

By freeing the memory of your vector, you'll only destroy your UserInteractions, but not the commands they are pointing to. If you use a c++11 compiler you can use a smart pointer.

struct UserInteraction
{
    UserInteractionType type;
    std::unique_ptr<Command> command;
    // or
    std::shared_ptr<Command> command;
};

That will automatically take care of deleting the commands. If not, I`d just delete all the commands in a loop iterating through the vector elements. (You could also write a costum destructor that deletes the command, together with a copy-assignment operator and -ctor (deep copy), as well as move-assignment operator and -ctor, but that seems like an overly complex solution)

Upvotes: 1

Related Questions