简体   繁体   English

容器中的C ++ STL内存管理

[英]C++ STL memory management in containers

I'm coding some mission critical code that I have to make sure it's absolutely free of memory leaks. 我正在编写一些关键任务代码,我必须确保它完全没有内存泄漏。 I've wrote a small function that allows me to retrieve the memory usage at runtime and I make measurements before and after executing some code (that should be leak free) to see if memory usage remains on the same level. 我写了一个小函数,允许我在运行时检索内存使用情况,并在执行某些代码(应该是无泄漏的)之前和之后进行测量,以查看内存使用情况是否保持在同一级别。

While debugging a piece of code that was 'leaking', I finally found the culprit to be a vector container. 在调试一段“泄漏”的代码时,我终于找到了成为矢量容器的罪魁祸首。

The minimal code that reproduces what I'm seeing is the following: 重现我所看到的最小代码如下:

vector<char*>* v = new vector<char*>();
int n = 1024*1024;
while (n--)
{
     v->push_back(new char[256]()); // A
}
for (vector<char*>::iterator it=v->begin() ; it!=v->end() ; ++it )
{
     delete[] (*it);
}
delete v;

If you run that code (disabling compiler optimizations of course, -O0 ) and put some trap at the end so that the program doesn't exit (like cin.ignore(); ) you would see that your program should be using around 20Mb or so of memory. 如果您运行该代码(当然禁用编译器优化, -O0 )并在最后放置一些陷阱以使程序不退出(如cin.ignore(); )您将看到您的程序应该使用大约20Mb记忆的左右。

I'd like to understand why does that happen. 我想知道为什么会这样。 There's a line I marked with A , where if you allocate a larger char array you would see that the 'remaining' memory at the end is larger too. 有一条我用A标记的行,如果你分配一个更大的char数组,你会发现末尾的“剩余”内存也更大。 I wouldn't call this a leak per se beause apparently that memory could be reused if I allocate and fill another STL container, but still I would have expected to have that memory completely freed when the code finishes. 我不会将此称为泄漏,因为如果我分配并填充另一个STL容器,显然可以重用内存,但我仍然期望在代码完成时完全释放该内存。

Can someone shed some light on to why is this memory still being used? 有人可以解释为什么这个记忆仍然被使用? And how may I 'free' it for real? 我怎么能把它“真正”释放呢?

Some details about my compiler environment: 关于我的编译环境的一些细节:

Using clang++: Apple LLVM version 6.0 (clang-600.0.51) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin13.3.0
Thread model: posix

Compiling with: g++ -std=c++11 -g -Wall -Wextra -Wpedantic -O0 main.cc -o main.out

First, there is no excuse for dynamically allocating your container in your scenario. 首先,没有理由在您的方案中动态分配容器。 Why? 为什么?

Second, it's a container of char* , and while it is responsible for managing those, you retain full and sole responsibility for whatever they point (or don't point) to! 其次,它是char*的容器,虽然它负责管理这些,但是对于他们指向(或不指向)的任何内容,您将保留全部和唯一的责任!

Consider using vector<char> , unique_ptr<char> , string or something like that as the element-type to let the vector take that task. 考虑使用vector<char>unique_ptr<char>string或类似的东西作为元素类型让vector接受该任务。

Finally, keep in mind that the runtime-system uses its own allocator built on the OS primitives, so allocating memory does not directly translate to a request to the OS, nor does freeing / deleting it immediately return it there. 最后,请记住,运行时系统使用自己的基于OS原语构建的分配器,因此分配内存不会直接转换为对OS的请求,也不会立即释放/删除它。
Doing so would be incredibly inefficient . 这样做会非常低效

If you really want to make sure freed memory is returned to the OS, you have basically two options (which both involve writing your own allocator, or finding and using one someone else built): 如果你真的想确保将释放的内存返回给操作系统,你基本上有两个选项(它们都涉及编写你自己的分配器,或者找到并使用其他人构建的):

  • Replace the replacable global allocation and deallocation functions with your own. 用您自己的替换可替换的全局分配和释放功能。
  • Use your own allocator for just those allocations (standard-containers are allocator-aware, which means you can provide your own allocator on a per-container basis). 使用您自己的分配器仅用于那些分配(标准容器是分配器感知的,这意味着您可以基于每个容器提供自己的分配器)。

After you are done, just ask your allocator to release everything back to the OS. 完成后,只需要求分配器将所有内容释放回操作系统。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM