繁体   English   中英

C ++ OpenMP代码中的内存泄漏

[英]Memory Leak in C++ OpenMP code

我编写了一个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;
    }
}

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

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

对于较小的分配,使用系统提供的堆。 有一种称为系统中断的东西,它是进程数据段结束的地方。 它可以通过brk(2)系统调用来移动以分配更多内存并向下移动以释放它。 由于每个进程只有一个堆区域,并且OS将其视为单个块,因此glibc中内置了一个特殊的堆管理器,可以进一步将该块细分为更小的分配。

C ++ new运算符从glibc调用malloc(3)来执行内存分配。 malloc(3)根据要分配的存储块的大小调用上述两种存储器分配机制之一。 C ++ delete运算符从glibc调用free(3)glibcmalloc(3)的释放对应物。 内存块被解除分配后发生的事情很大程度上取决于它首先如何分配。

使用mmap(2)机制分配的内存通过使用munmap(2)取消munmap(2)来解除分配。 这将从进程的虚拟地址空间中删除内存映射,并释放用于支持分配的物理内存页。

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

暂无
暂无

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

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