【问题标题】:C++ memory leak when creating an array创建数组时的 C++ 内存泄漏
【发布时间】:2016-10-21 13:41:20
【问题描述】:

在我的 C++ 游戏中,我有一个指向 EnemyTypes 的指针数组。我使用 Visual Leak Detector 检测内存泄漏,它告诉我以下代码有泄漏:

vector<EnemyType*> enemyTypes(number_of_lines);

for (int i = 0; i < number_of_lines; i++)
{
    enemyTypes[i] = new EnemyType();
}

假设number_of_lines 在这种情况下是 3。我怎么可能在这里制造泄漏?我能做点什么吗?

我大约一个月前开始学习 C++,现在每天都在学习,但是如果没有人解释我就无法理解某些东西(比如这样)。

编辑:我已修改代码以使用向量而不是普通数组。

【问题讨论】:

  • 你试过向量吗?
  • 只有在忘记释放内存时才会产生泄漏。上面的代码没有显示这个问题。创建一个 MCVE:stackoverflow.com/help/mcve
  • 如果enemyTypes 是一个方法的本地并且你没有delete 每个元素(和数组本身)那么你就有泄漏。考虑使用std::vector&lt;EnemyType&gt;,动态内存并不总是可取的,使用时,适当的智能指针可以利用管理部分。
  • 这是我为学校制作的游戏,目前还不允许使用智能指针。我考虑过使用向量,但使用普通数组似乎更适合学习目的,但我现在会重新考虑使用它。
  • 你使用指针有什么原因吗?您还可以将 EnemyType 存储在数组中(甚至更好:在向量中)。

标签: c++ memory-leaks


【解决方案1】:

来自您的原始代码:

EnemyType** enemyTypes{ new EnemyType*[number_of_lines] };

for (int i = 0; i < number_of_lines; i++)
{
    enemyTypes[i] = new EnemyType();
}

当您在 C++ 中使用 new 分配内存时,您必须使用 delete(或在分配数组时使用 delete[],例如您的 enemyTypes)释放它。

我们只看到您的部分代码,但我猜当您不再需要内存时,您不会进行任何释放。

顺便说一句,你应该避免分配内存,或者通过托管指针分配它:

#include <vector>
#include <memory>

// ...

std::vector<std::unique_ptr<EnemyType>> enemy_types(number_of_lines);

for (auto& enemy_type : enemy_types)
{
    enemy_type = std::make_unique<EnemyType>();
}

根据您使用数据的方式,您甚至可以避免使用指针:

std::vector<EnemyType> enemy_types(number_of_lines);

【讨论】:

    【解决方案2】:

    操作员new动态分配内存。

    某些代码最终需要使用相应的运算符delete 释放该内存。如果您的代码不这样做,则永远不会释放内存。如果您的程序丢失轨道(例如,用于保存 new 的结果的指针不复存在),这将成为泄漏。

    您的代码稍作修改的版本

    int func()
    {
        EnemyType** enemyTypes{ new EnemyType*[number_of_lines] };
    
        for (int i = 0; i < number_of_lines; i++)
        {
             enemyTypes[i] = new EnemyType();
        }
    }
    

    随着函数返回,指针enemyTypes 不再存在(因为它超出了范围)。结果是第一次使用运算符new 创建的内存永远不会被释放,并且不存在指向它的指针。由于无法访问该内存,因此也无法访问循环中运算符new 的结果(因为这些结果的唯一存储位置是enemyTypes 标识的动态分配数组中)。

    因此,所有内存都在此时泄漏(动态分配的内存无法由您的程序恢复,除非您使用标准 C++ 范围之外的某些技术)。各种内存检查器 - 如果您使用它们 - 将相应地报告泄漏......无论是在函数返回的地方,还是在程序终止时。

    【讨论】:

      【解决方案3】:

      使用运算符 new 时,请确认您删除了您创建的每个对象。

      一个不错的选择是使用来自 STL 或 boost 库的智能指针。它们会在您的对象未使用时自动删除,从而避免内存泄漏。

      【讨论】:

        【解决方案4】:

        事实证明我从未释放内存(正如其他人告诉我的那样),但 Visual Leak Detector 只是向我显示了分配内存的位置,而不是发生泄漏的位置。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-07-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-05
          • 1970-01-01
          相关资源
          最近更新 更多