Visual C++矢量擦除增加了内存使用率
Visual C++ vector erase increases memory usage?
这是我在stackoverflow上的第一个问题。我在很大程度上用以下代码行寻找了我所经历的原因:
unsigned long long _mem1= getUsedVirtualMemory();
vector.erase(vector.begin() + _idx);
contained= false; // don't stop the loop
_idx--; // the removed object has redefined the idx to be consider.
_mem1 = getUsedVirtualMemory() - _mem1;
if (_mem1 > 0) printf("Memory - 2 mem1: %lun" , _mem1);
我的程序消耗了大量内存,经过密集的调试、一些打印和耗时的分析,我得出了这一点:
getUsedVirtualMemory使用以下代码实现:
PROCESS_MEMORY_COUNTERS_EX pmc;
GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*) &pmc, sizeof(pmc));
SIZE_T virtualMemUsedByMe = pmc.PrivateUsage;
return virtualMemUsedByMe;
以获得由所述进程分配的虚拟存储器的量;向量是对象(而不是指针)的向量。
在大多数情况下,矢量的擦除方法似乎如预期的那样工作,但在某些情况下,该矢量的擦除方式似乎增加了进程使用的内存,而不是释放它。我在代码周围的许多情况下都使用Windows系统函数GetProcessMemoryInfo来调试这个问题,它似乎返回了使用过的虚拟内存的实际值。
我使用的是Visual Studio C++2010 Professional。
如果需要更多信息,请告诉我。
谢谢你的回复。
更新:
你在回复中写的所有内容都是正确的,我忘记了以下细节:
- 我已经知道向量有一个大小(元素的实际数量)和一个容量(分配给存储元素的插槽)
- 我已经知道擦除方法不会释放内存(我找了很多关于该方法的文档)
- 最后,我稍后会将其他元素添加到该向量中,所以我不需要收缩该向量
实际问题是,在这种情况下,最后一行代码中的"_mem1"值显示出1.600.000字节的差异:内存增加不合理,而我预计为0字节。
此外,在运算后使用的内存值将小于第一个的情况下,我预计会有一个非常大的数字来解释,例如在无符号整数减法定义行为吗?
我得到的不是预期的结果,而是一个大于0但相对较短的值。
为了更好地了解问题的发生率,在这段代码上迭代数千次,意外地分配了大约20 Gb的虚拟内存。
矢量具有:
- 一个
size()
,它指示容器中有多少活动元素 - 一个
capacity()
,它告诉内存中保留了多少个元素
erase()
将大小更改为零。它不会释放分配的内存容量。
您可以使用shrink_to_fit()来确保容量减小到所需大小。
如果需要,用resize()
更改大小或用reserve()
更改容量可能会增加分配的内存,但如果新的大小/容量低于现有容量,则不一定会释放内存。
这是因为擦除不会释放内存,它只是擦除元素。看看草药。
要(真正)释放你可以做的内存(从参考链接):
正确的方法"收缩到合适";矢量
那么,我们能写一个压缩向量的代码吗;以适应";使得它的容量刚好足以容纳所包含的元素?显然reserve()不能完成这项工作,但幸运的是,确实有一种方法:
vector<Customer>( c ).swap( c );
// ...now c.capacity() == c.size(), or
// perhaps a little more than c.size()
vector.ersase()
只能保证从向量中删除元素,不能保证减少底层数组的大小(因为这个过程相当昂贵)。IE:它只将数据清零,不一定会解除分配。
如果你需要一个只有它包含的元素那么大的向量,请尝试使用vector.resize(vector.size())
IIRC在windows上的Debug构建中,new
实际上是#defined
,而DEBUG_NEW
会导致(除其他外)内存块实际上没有被释放,而只是被标记为"已删除"。
你在发布版本中也有同样的行为吗?
问题的一部分可能是std::vector无法从底层内存缓冲区中删除条目,如果它们不在缓冲区的末尾(您的缓冲区不是),那么保留的条目将被移动到一个完全不同的缓冲区。由于您正在擦除第一个元素,所以允许std::vector(因为标准状态是擦除()会使擦除点处/之后的所有迭代器失效,在您的情况下,所有迭代者都会失效)分配一个额外的缓冲区来将剩余元素复制到,然后在复制后丢弃旧的缓冲区。因此,您可能会同时使用两个缓冲区,并且您的内存管理器可能不会将丢弃的缓冲区返回到操作系统,而是保留内存,以便在后续分配中重复使用。这将解释循环迭代中单个的内存使用量增加的原因。
- 将字符串存储在c++中的稳定内存中
- C++ 指针的内存地址和指向数组的内存地址如何相同?
- Win32编译器选项和内存分配
- 当vector是tje全局变量时,c++中vector的内存管理
- 带内存和隔离功能的SQLite
- 从 C++11 代码中获取系统内存和 CPU 使用率
- 加载时间,遍历时间,不同数据段C/C 的内存使用率
- 使用 PID 获取内存和 CPU 使用率
- Linux:如何测量进程中线程的内存使用率
- 当CPU使用率高时,OpenCV会堆积内存吗
- Win32 C++中的DrawText会增加内存使用率
- Boost managed_mapped_file:设置允许的最大内存使用率
- 远程电脑的 CPU 使用率和内存状态
- STXXL的高内存使用率
- 内存使用率上升.释放的内存不会被重复使用
- Visual C++矢量擦除增加了内存使用率
- C、 所有平台中进程的C++CPU使用率和内存使用率+当前时间的可用网络下行链路带宽
- 具有低内存使用率的自平衡AVL树
- 内存池:对于大于缓存行大小的结构体,它们会提高缓存使用率吗?
- 在内存不增加的情况下逐渐提高cpu使用率.的想法