gpt4 book ai didi

c++11 - C++ std::vector 在特定情况下表现得像泄漏内存

转载 作者:行者123 更新时间:2023-12-04 15:22:07 25 4
gpt4 key购买 nike

我发现了一种情况,向量表现得像内存泄漏,可以将其归结为一个最小的工作示例。在这个例子中,我(在一个函数中)创建了一个包含三个 char 向量的向量。首先,这些 char 向量被插入大量元素,并且它们的容量缩小到它们的大小。然后在大向量上分配一个元素大小的向量。现在的问题是,使用的内存太大,即使函数返回并且向量被破坏,内存也不会被释放 .如何找回内存?为什么会表现出这种行为?我能做些什么来避免这种泄漏行为?

这里是示例代码(对不起,长度):

#include <iostream>
#include <vector>
#include <string>
#include <fstream>

using namespace std;

// see http://man7.org/linux/man-pages/man5/proc.5.html at /proc/[pid]/status
string meminfo() {
// memory information is in lines 11 - 20 of /proc/self/status
ifstream stat_stream("/proc/self/status",ios_base::in);

// get VmSize from line 12
string s;
for ( int linenum = 0; linenum < 12; ++linenum )
getline(stat_stream,s);
stat_stream.close();
return s;
}

void f() {
vector<vector<char>> mem(3); // with 1,2 memory is fine
size_t size = 16777215; // with 16777216 or greater memory is fine
for ( vector<char>& v : mem ) {
for ( unsigned int i = 0; i < size; ++i )
v.push_back(i);
v.shrink_to_fit(); // without this call memory is fine
}

cout << "Allocated vectors with capacities ";
for ( vector<char>& v : mem )
cout << v.capacity() << ", ";
cout << endl << "used memory is now: " << meminfo() << endl;

for ( vector<char>& v : mem ) {
v = vector<char>{1};
if ( v.size() != v.capacity() )
cout << "Capacity larger than size." << endl;
}
cout << "Shrinked vectors down to capacity 1." << endl
<< "Used memory is now: " << meminfo() << endl;
}

int main() {
cout << "At beginning of main: " << meminfo() << endl;
f();
cout << "At end of main: " << meminfo() << endl;
return 0;
}

我机器上的输出:
At beginning of main: VmSize:      12516 kB
Allocated vectors with capacities 16777215, 16777215, 16777215,
used memory is now: VmSize: 78060 kB
Shrinked vectors down to capacity 1.
Used memory is now: VmSize: 61672 kB
At end of main: VmSize: 61672 kB

但是,valgrind 没有发现内存泄漏。

我猜示例中的参数取决于系统以显示奇怪的行为。我使用带有 g++ 4.8.2 和 x86_64 内核的 Linux Mint Debian 版。我编译:
g++ -std=c++11 -O0 -Wall memory.cpp -o memory

并尝试了 -O3 并且没有明确的优化设置。

一些有趣的观点是:
  • 当我更换 v = vector<char>{1};通过 v.clear(); v.shrink_to_fit(); v.push_back(1);问题保持不变。用 v = vector<char>(16777215); 替换大向量的推送和收缩“解决”内存问题。
  • 16777215 = 2^24 - 1,所以也许它必须对内存边界做一些事情。
  • 此外,从程序在 main 开始时使用的内存(12516 kiB)加上大向量的内存,可以预期程序总共应该使用大约 3*16777216 B + 12516 kiB = 61668 kiB,这大约是它最终使用的内存。

  • 在现实世界的应用程序中,我使用向量来收集应该应用于 FEM 模拟的刚度矩阵的操作。由于我想达到可用内存的极限(也在速度方面),我需要保存未释放的内存以避免交换。由于交换确实发生,我假设 VmSize 值是可靠的。

    最佳答案

    问题是您误解了在 C++ 上下文中“释放”内存的含义。当您的应用程序释放内存(使用 shrink_to_fit 或删除对象或其他)时,它实际上只是将内存释放到 C++ 运行时,而不一定将其释放回系统以供其他进程使用。 C++ 运行时可能会选择保留内存以供稍后在同一进程中重用。

    通常,当内存碎片时会发生这种情况——空闲内存被使用中的内存包围(在程序的 VM 空间中)。只有当释放的内存位于程序内存空间的末尾时,C++ 运行时才会选择(或能够)将其返回给系统。

    通常这种内存保留不是问题,因为它通常可以在应用程序请求更多内存时重复使用。您可能遇到的问题是,由于 C++ 运行时无法移动正在使用的内存块,您可能无法重用太小的空闲 block 。运行时可能会使用各种技巧和启发式方法来尝试避免这种情况,但它们并不总是有效。

    关于c++11 - C++ std::vector 在特定情况下表现得像泄漏内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26895050/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com