Abh*_*bhi 3 c++ memory memory-leaks openmp
我编写了一个c ++ openmp代码,它在并行区域中有一个动态分配的内存私有变量,该区域在while循环中.在每个循环中,在并行区域的末尾释放动态分配的内存.我在每次分配和释放后通过linux机器上的/ proc/self/stat文件监视内存.我发现驻留集大小的内存较少.为什么会这样?代码是这样的 -
float *dynm;
while(condition)
{
pragma omp parallel shared(list of variables) private(dynm)
{
read_values_from_/proc/self/stat_print_rss;
dynm = new float[size];
read_values_from_/proc/self/stat_print_rss;
pragma omp for schedule(static, chunk) nowait
for(counter)
{
do_operation;
}
delete []dynm;
read_values_from_/proc/self/stat_print_rss;
}
}
Run Code Online (Sandbox Code Playgroud)
测量RSS不是一种非常准确的搜索内存泄漏的方法,因为它的计算方式非常复杂.有特殊的内存调试器valgrind或内置的调试器glibc可以告诉你内存是否泄漏.您还必须了解glibc使用两种完全不同的机制来动态分配内存.
对于大型分配,它使用mmap(2)系统调用执行私有匿名内存映射.此方法只能分配大小为系统页面大小的倍数的块(在大多数现代体系结构上为4 KiB),因此不适合小分配.当浪费太多内存时,它甚至不适合更大的分配,例如,如果你想分配17 KiB的块,那么必须分配20 KiB(5倍4 KiB)并且15%的内存将被分配浪费了.
对于较小的分配,使用系统提供的堆.有一种称为系统中断的东西,它是进程数据段结束的地方.可以通过brk(2)系统调用将其移动以分配更多内存,然后向下移动以释放它.由于每个进程只有一个堆区域,并且OS将其视为单个块,因此内置了一个特殊的堆管理器glibc,可以进一步将该块细分为更小的分配.
C++的new操作员调用malloc(3)从glibc执行存储器分配.malloc(3)根据要分配的存储块的大小,调用上述两种存储器分配机制之一.C++ delete运算符调用free(3)从中glibc释放对应的malloc(3).内存块被解除分配后发生的事情很大程度上取决于它首先如何分配.
使用该mmap(2)机制分配的内存通过取消分配来解除分配munmap(2).这将从进程的虚拟地址空间中删除内存映射,并释放用于支持分配的物理内存页.
对于在堆中分配的内存而言,事情变得更加复杂,并且更大程度上取决于用于管理它的算法.如果被释放的块不是位于堆的末尾,而是位于其他位置,那么堆大小不能减少,因为在高端内存地址上有其他分配.这只是所谓的堆碎片表现形式的众多形式之一.不会看到已用内存减少的另一个可能原因是堆管理器可能决定不会在预期可能的将来分配时移回中断位置,并且调用brk(2)是一项昂贵的操作.
| 归档时间: |
|
| 查看次数: |
685 次 |
| 最近记录: |