【问题标题】:C++ memory doesn't get freed for seemingly no reasonC++ 内存似乎没有理由被释放
【发布时间】:2020-08-10 14:21:40
【问题描述】:

我正在使用 Qt 和 OpenGL 开发 3D 编辑器,但似乎无缘无故地遇到了严重的“内存泄漏”。我已将问题隔离到一个类中,如下所示:

template <size_t SIZE>
class GlVoxelChunk {
private:
    gl::FunctionsX *glFuncs; // unmanaged pointer, points to a global variable
    Color data[SIZE * SIZE * SIZE];
    Vec3i pos;
    GLuint glTexture = 0;

    std::vector<GLfloat> vertices;
    std::vector<GLbyte> colors;
    std::vector<GLuint> elements;
    ...
}

// all chunks are stored like this:
std::map<Vec3i, GlVoxelChunk<16>> 

这里的两个大内存猪是 3D 数组和包含上传到 GL 的数据的向量。

当加载一个大型模型并用它填充这些块时,内存使用量会上升到大约 3GB。当删除模型并因此再次删除这些块时,它不会出现任何问题。我的第一个猜测是这些块永远不会被破坏,但事实并非如此。我:

  • instance对chunk进行计数,删除模型后计数回0
  • 使用实例计数对象创建了另一个向量,这些对象也都被正确清除
  • 使用 memgrind 运行我的应用程序以检测任何丢失的内存,但什么也没找到
  • 检查是否使用 gdb 调用了析构函数并且它们都调用了

我自己什至不手动管理任何内存,这些块都存储在std::map 中。我可以肯定地说这些向量是罪魁祸首,因为当我根本不填充它们时,删除 3D 对象时内存使用量会下降到接近于零。更奇怪的是,如果我填充它们,没有内存被释放,甚至这些 3D 数组也没有被释放。

在这一点上,我不知道该怎么办。如果 Memgrind 甚至无法检测到 3GB 内存泄漏,它就毫无用处。我还能做什么?

【问题讨论】:

  • 你如何看待或衡量它没有被释放?
  • 如果 memgrind 没有检测到内存泄漏,这表明内存可能没有泄漏;相反,它可能已被分配并且从未被释放,但由于程序中的其他地方仍然存在指向已分配内存的指针,因此它不能算作泄漏,因为程序仍然有能力释放它。 (我最常在以下情况下看到这种行为,例如程序不断向向量或其他数据结构添加新项目,但忘记清除向量或删除项目,以便向量无限期地变得越来越大)
  • @RoQuOTriX KSysGuard 和 htop 中显示的内存使用量为 3GB。
  • 您是否使用操作系统实用程序来告诉您每个应用程序使用了多少内存?如果是这样,释放应用程序内部的内存并不一定会将其返回给操作系统。因此,即使没有泄漏,操作系统报告的内存量也不一定会下降。释放的内存可在应用程序中重复使用。
  • 注意:shrink_to_fit 是一个礼貌的请求,如果程序看到不收缩的好处,可以忽略它。

标签: c++ opengl memory memory-leaks


【解决方案1】:

当向量被清除或delete 分配了new 等时,析构函数被调用,内存被释放并可供新用途使用。但它不一定返回给操作系统。通常编译器运行时库将保留内存,它将用于满足程序的新分配,而无需再次涉及操作系统。这加快了未来的分配速度。

【讨论】:

  • 你可能是对的,因为当我在删除第一个对象后加载另一个对象时,内存使用量仍然是 3GB。因此,应用程序之前声明的内存正在被重用。
  • @J.Schultke 不要听起来傲慢或任何东西,但是是的,我知道我是对的。如果你看一下 libc++ 代码和 Linux 内核内存管理代码,你会发现我说的是正确的。证据全都公开供您检查。
  • 这听起来确实很自大:)
  • @J.Schultke 我知道。但我不知道如何表达它。如果您深入了解所涉及的实际代码,您会发现事情就是这样。我不知道如何表达而不显得傲慢,所以请原谅我。我只是想帮忙。
  • 几个内存分配器直接从操作系统分配大对象,然后直接释放给操作系统。我猜 J. Schultke 的人不会这样做。如果他愿意,他可以直接从操作系统分配内存。 (Windows:VirtualAlloc。Linux:mmap)
猜你喜欢
  • 2018-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-10
  • 2010-12-18
  • 2018-08-27
相关资源
最近更新 更多