重复清除和填充 std::vector 时内存使用量持续增长是否正常?

发布于 2024-09-07 22:54:44 字数 462 浏览 3 评论 0原文

我有一个名为 OGLSHAPE 的类的 std::vector 。

每个形状都有一个 SHAPECONTOUR 结构体向量,其中有一个 float 向量和一个 double 向量向量。它还有一个轮廓结构的向量,其中有一个浮点向量。

最初,我的程序使用 8.7 MB 的 RAM 启动。我注意到,当我开始填充这些内容(例如添加双精度数和浮点数)时,内存很快就会变得相当高,然后趋于平稳。当我清除OGLSHAPE向量时,仍然使用了大约19MB。然后,如果我再推送大约 150 个形状,然后清除这些形状,我现在使用大约 19.3MB 的内存。我本以为从逻辑上讲,如果第一次从 8.7 到 19,那么下一次它会上升到 30 左右。我不确定它是什么。我以为这是内存泄漏,但现在我不确定。我所做的就是将数字推入 std::vectors,没有别的。所以我希望能恢复我所有的记忆。什么可能导致这种情况?

编辑

这是由于分配大量小东西而产生的内存碎片, 怎么解决呢?

I have a std::vector of a class called OGLSHAPE.

each shape has a vector of SHAPECONTOUR struct which has a vector of float and a vector of vector of double. it also has a vector of an outline struct which has a vector of float in it.

Initially, my program starts up using 8.7 MB of ram. I noticed that when I started filling these these up, ex adding doubles and floats, the memory got fairly high quickly, then leveled off. When I clear the OGLSHAPE vector, still about 19MB is used. Then if I push about 150 more shapes, then clear those, I'm now using around 19.3MB of ram. I would have thought that logically, if the first time it went from 8.7 to 19, that the next time it would go up to around 30. I'm not sure what it is. I thought it was a memory leak but now I'm not sure. All I do is push numbers into std::vectors, nothing else. So I'd expect to get all my memory back. What could cause this?

Edit

It's memory fragmentation from allocating lots of small things,
how can that be solved?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

七分※倦醒 2024-09-14 22:54:45

调用 std::vector<>::clear() 不一定释放所有分配的内存(它取决于 std::vector<> 的实现)。这样做通常是为了优化以避免不必要的内存分配。

为了真正释放实例所持有的内存,只需执行以下操作:

template <typename T>
inline void really_free_all_memory(std::vector<T>& to_clear)
{
    std::vector<T> v;
    v.swap(to_clear);
}

// ...
std::vector<foo> objs;

// ...
// really free instance 'objs'
really_free_all_memory(objs);

创建一个新的(空)实例并将其与您想要清除的向量实例交换。

Calling std::vector<>::clear() does not necessarily free all allocated memory (it depends on the implementation of the std::vector<>). This is often done for the purpose of optimization to avoid unnessecary memory allocations.

In order to really free the memory held by an instance just do:

template <typename T>
inline void really_free_all_memory(std::vector<T>& to_clear)
{
    std::vector<T> v;
    v.swap(to_clear);
}

// ...
std::vector<foo> objs;

// ...
// really free instance 'objs'
really_free_all_memory(objs);

which creates a new (empty) instance and swaps it with your vector instance you would like to clear.

遇到 2024-09-14 22:54:45

使用正确的工具来观察内存使用情况,例如(在 Windows 上)使用 Process Explorer 并观察专用字节。不要查看虚拟地址空间,因为它显示正在使用的最高内存地址。碎片化是两个价值观之间存在巨大差异的原因。

还要意识到应用程序和操作系统之间有很多层:

  • std::vector 不一定立即释放所有内存(请参阅 hkaiser 的提示)
  • C 运行时并不总是将所有内存返回给操作系统
  • 操作系统的堆例程可能无法释放所有内存,因为它只能释放整页(4 KB)。如果 4KB 页中的 1 个字节仍被使用,则该页无法释放。

Use the correct tools to observe your memory usage, e.g. (on Windows) use Process Explorer and observe Private Bytes. Don't look at Virtual Address Space since that shows the highest memory address in use. Fragmentation is the cause of a big difference between both values.

Also realize that there are a lot of layers in between your application and the operating system:

  • the std::vector does not necessarily free all memory immediately (see tip of hkaiser)
  • the C Run Time does not always return all memory to the operating system
  • the Operating System's Heap routines may not be able to free all memory because it can only free full pages (of 4 KB). If 1 byte of a 4KB page is stil used, the page cannot be freed.
请止步禁区 2024-09-14 22:54:45

这里有一些可能的事情在起作用。

首先,内存在最常见的 C 和 C++ 运行时库中的工作方式是,一旦将其从操作系统分配给应用程序,就很少会返回给操作系统。当您在程序中释放它时,new 内存管理器会保留它,以防您再次请求更多内存。如果您这样做,它会将其返还给您以供重复使用。

另一个原因是向量本身通常不会减小其大小,即使您清除它们。他们将其拥有的“容量”保持在最高水平,以便更快地重新填充它们。但是,如果向量被破坏,该内存将返回到运行时库以再次分配。

因此,如果您没有销毁向量,它们可能会在内部为您保留内存。如果您在操作系统中使用某些东西来查看内存使用情况,它可能不知道有多少“空闲”内存在运行时库中等待使用,而不是返回给操作系统。

内存使用量略有增加(而不是根本不增加)的原因可能是由于碎片。这是一种复杂的切线,但足以说明分配大量小对象会使运行时库在需要时更难找到大块。在这种情况下,它无法重用您已经释放的一些内存,因为它是由许多小块组成的。所以它必须向操作系统请求一个大块。

There are a few possible things at play here.

First, the way memory works in most common C and C++ runtime libraries is that once it is allocated to the application from the operating system it is rarely ever given back to the OS. When you free it in your program, the new memory manager keeps it around in case you ask for more memory again. If you do, it gives it back for you for re-use.

The other reason is that vectors themselves typically don't reduce their size, even if you clear() them. They keep the "capacity" that they had at their highest so that it is faster to re-fill them. But if the vector is ever destroyed, that memory will then go back to the runtime library to be allocated again.

So, if you are not destroying your vectors, they may be keeping the memory internally for you. If you are using something in the operating system to view memory usage, it is probably not aware of how much "free" memory is waiting around in the runtime libraries to be used, rather than being given back to the operating system.

The reason your memory usage increases slightly (instead of not at all) is probably because of fragmentation. This is a sort of complicated tangent, but suffice it to say that allocating a lot of small objects can make it harder for the runtime library to find a big chunk when it needs it. In that case, it can't reuse some of the memory it has laying around that you already freed, because it is in lots of small pieces. So it has to go to the OS and request a big piece.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文