【问题标题】:Problems when freeing memory when I have undo/redo撤消/重做时释放内存时出现问题
【发布时间】:2015-02-06 22:24:00
【问题描述】:

我正在为一个类开发一个项目,我们应该在其中实现文本编辑器的基本功能,包括撤消和重做。我目前的撤消/重做功能正常工作,唯一的问题是,当我尝试从告诉我们要执行什么的 Command 对象中释放内存时,我遇到了 valgrind 错误。

这个Command 对象是命名空间中结构的一部分,如下所示:

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

目前,我将用户发出的每个命令存储在名为 undoStack<UserInteraction> 类型的 std::vector 中。我还有一个相同类型的redoStack,它也是一个 std::vector。存储每个命令如下所示:

    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

当用户按下 ctrl+x(退出程序)时,我需要释放每个被推入向量的 UserInteraction。否则,我发出的任何命令都会给我这样的错误:

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

输入的每个命令都会使丢失的字节数增加 4。

我想我只需要在退出命令中释放每个向量使用的所有内存,但是人们使用的所有当前解决方案似乎仍然给我内存泄漏。这是我的退出方法的两个版本(这两个版本仍然给我内存泄漏):

第一次尝试:

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

我第二次尝试释放内存:

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

那么我如何才能真正释放两个向量中的所有内容?

【问题讨论】:

  • 很难看出问题出在什么地方。
  • @RSahu 部分问题是我的程序一开始就乱七八糟,项目规则说我必须在不更改原始代码的情况下实现所有内容。要获得所有内容的总体概述,需要大量的代码:(

标签: c++ vector memory-leaks valgrind


【解决方案1】:

通过释放向量的内存,您只会破坏 UserInteractions,但不会破坏它们指向的命令。如果您使用 c++11 编译器,则可以使用智能指针。

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

这将自动删除命令。如果没有,我会删除循环遍历向量元素的所有命令。 (您还可以编写删除命令的 costum 析构函数,以及复制赋值运算符和 -ctor(深拷贝),以及移动赋值运算符和 -ctor,但这似乎是一个过于复杂的解决方案)

【讨论】:

  • 这行得通 :) 感谢上帝的 unique_ptr,我正要开始为每个类编写析构函数/赋值/复制构造函数。谢谢!
猜你喜欢
  • 2010-10-26
  • 2023-03-03
  • 1970-01-01
  • 2011-08-04
  • 1970-01-01
  • 1970-01-01
  • 2016-03-02
  • 1970-01-01
相关资源
最近更新 更多