Joh*_*ohn 6 memory-leaks vector c++11
我发现了一种情况,其中向量的行为类似于泄漏内存,并且可以将其归结为最小的工作示例.在这个例子中,我(在一个函数中)生成一个包含三个char向量的向量.首先,这些char矢量被推入大量元素,它们的容量缩小到它们的大小.然后在大矢量上分配单元素大小的矢量.现在的问题是,使用的内存太大,即使函数返回并且向量被破坏,内存也不会被释放.我如何获得回忆?为什么它显示这个bahaviour?我该怎么做才能避免这种泄漏行为?
这里是示例代码(抱歉长度):
#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;
}
Run Code Online (Sandbox Code Playgroud)
我机器上的输出:
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
Run Code Online (Sandbox Code Playgroud)
但是,valgrind看不到内存泄漏.
我想这个例子中的参数是系统相关的,以显示奇怪的行为.我使用Linux Mint Debian Edition和g ++ 4.8.2以及x86_64内核.我编译:
g++ -std=c++11 -O0 -Wall memory.cpp -o memory
Run Code Online (Sandbox Code Playgroud)
并尝试-O3并没有明确的优化设置.
一些有趣的观点是:
v = vector<char>{1};的v.clear(); v.shrink_to_fit(); v.push_back(1);问题保持不变.通过v = vector<char>(16777215);"解决"内存问题来替换大矢量的推动和收缩.在现实世界的应用程序中,我使用向量来收集应该应用于FEM模拟的刚度矩阵的操作.由于我想达到可用内存的可能性(也就速度而言),我需要保存不同的内存以避免交换.由于交换确实发生,我认为VmSize值是可靠的.
问题是您误解了 C++ 上下文中“释放”内存的含义。当您的应用程序释放内存(使用shrink_to_fit或删除对象或其他方式)时,它实际上只是将内存释放给 C++ 运行时,而不一定将其释放回系统以供其他进程使用。C++ 运行时可以选择保留内存以便稍后在同一进程中重用。
通常,当内存碎片化时,就会发生这种情况——空闲内存(在程序的虚拟机空间中)被正在使用的内存包围。只有当释放的内存位于程序内存空间的末尾时,C++运行时才会选择(或能够)将其返回给系统。
一般来说,这种内存保留不是问题,因为当应用程序请求更多内存时,通常可以重用它。您可能遇到的问题是,由于 C++ 运行时无法移动正在使用的内存块,因此您可能无法重用太小的空闲块。运行时可能会使用各种技巧和启发法来尝试避免这种情况,但它们并不总是有效。