簡體   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