2012-09-20 92 views
3

我写了一个C++ openmp代码,它在并行区域中有一个动态分配的内存私有变量,该区域在while循环中。内存动态分配在每个循环的并行区域结束时释放。我正在通过linux机器上的/ proc/self/stat文件监视内存,在每次分配和释放后。我在居民组大小中发现一些内存较少。为什么这样?该代码是一样的东西 -C++ OpenMP代码中的内存泄漏

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; 
    } 
} 
+2

'do_operation'里有什么? – Hbcdev

+0

dynm数组已被线程用于计算 – Abhi

回答

5

测量RSS是不是搜索,因为正在计算它的方式很复杂的内存泄漏一个非常准确的方法。有特殊的内存调试器,如valgrind或内置于glibc的内存调试器可以告诉你内存是否泄漏。你还必须明白,glibc使用两种完全不同的机制来动态分配内存。

对于大型分配,它使用mmap(2)系统调用执行专用匿名内存映射。此方法只能分配大小为系统页大小倍数的块(在大多数现代体系结构中为4 KiB),因此不适用于小分配。当浪费太多内存时,甚至不适用于较大的分配。如果您想要分配一个17 KiB的块,那么必须分配20 KiB(5倍4 KiB),并且将浪费15%的内存。

对于较小的分配,使用系统提供的堆。有一种叫的系统中断,这是过程的数据段结束的地方。可以调用brk(2)系统调用分配更多内存并释放内存。由于每个进程只有一个堆区,操作系统将其视为一个块,因此glibc中内置了一个特殊的堆管理器,可以将该块进一步细分为更小的分配。

C++ new运算符调用malloc(3)glibc执行内存分配。 malloc(3)取决于要分配的存储器块的大小调用上述两个存储器分配机制中的一个。 C++ delete运营商从glibc调用free(3),这是malloc(3)的重新分配对应部分。内存块解除分配后会发生什么很大程度取决于它是如何分配的。

使用mmap(2)机制分配的内存通过将其与munmap(2)取消映射而取消分配。这会从进程的虚拟地址空间中删除内存映射,并释放用于备份分配的物理内存页面。

对于在堆中分配的内存而言,事情是比较复杂的,并且更大程度上取决于用于管理它的算法。如果被释放的块不在堆的末尾,而是位于其他位置,那么堆大小不能减少,因为在高位内存地址上有其他分配。这只是所谓的堆碎片表现出来的许多形式之一。另一个可能的原因是不会看到已使用内存的减少,因为堆管理器可能会决定不考虑未来可能的分配情况而回退中断位置,并且调用brk(2)是一项昂贵的操作。

+0

感谢您的解释......这是非常有用的 – Abhi