当valgrind没有出现任何泄漏时,驻留内存增加

piy*_*ush 2 c c++

我添加了一个在我的C++程序代码中重启的选项.每次它重新启动我可以看到驻留内存增加,而Valgrind是不显示任何泄漏.有什么可以常驻内存增加的原因.

Mat*_*son 9

这有几个可能的原因:

  1. 你可能正在增长记忆力,但实际上并没有泄漏:vector<int> v; for(;;) v.push_back(1);在几秒钟之内就会出现内存不足的情况,但根据valgrind的说法,这不是泄漏.
  2. 堆是你的"res"内存的一部分,所以如果你有一些东西分配x MB的堆内存,然后释放它,除非操作系统实际上需要那个内存用于其他目的,它将作为你的应用程序内存的一部分.(实际上,它比这复杂得多,但对于这个讨论,这张图片是有效的).
  3. 堆碎片.如果你在堆中分配和释放东西,并且内存大小变化很大,那么内存确实是"免费的",但是堆中的块可能太小而无法用于下一次分配,所以"新鲜"的一块堆被切断了.想象一下,你从一块长木头开始,然后把它剪下来适合某个地方,然后将它拆下并再次切割 - 你再也不能让它恢复到最大尺寸.(再次,实际上,它比这复杂得多,但对于这个讨论来说已经足够了).

您可能希望将valifind的massif工具用于valgrind --tool=massif prog识别#1等数据,其中数据随着时间的推移而逐渐增加.

编辑:从链接中的页面:

Massif是一个堆分析器.它测量程序使用的堆内存量.这包括有用空间和为记账和对齐目的分配的额外字节.它也可以测量程序堆栈的大小,但默认情况下不会这样做.

mem_heap_extra_B被分配为"填充"和"开销"的字节数.它通常只占总分配大小的一小部分,但如果您有许多非常小的分配,它可以控制堆使用.

mem_stacks_B是应用程序使用的堆栈字节数(默认情况下,这不会被测量,因为它会大大减慢代码速度).

以此程序为例:

#include <vector>

int main(int argc, char **argv)
{
    (void)argv;   // Not used. 

    const int size = 10000;

    std::vector<int*> v(size);

    switch (argc)
    {
    case 1:
        for(int i = 0; i < size; i++)
        {
            v[i] = new int;
        };

        for(int i = 0; i < size; i++)
        {
            delete v[i];
        };
        break;

    case 2:
    {
        int *t = new int [size];
        for(int i = 0; i < size; i++)
        {
            v[i] = t+i;
        };

        delete [] t;
        break;
    }

    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

以下是valgrind --tool=massif ./a.out(case 1:代码的变体)的输出(在峰值使用时):

time=2872338
mem_heap_B=120000
mem_heap_extra_B=200008
mem_stacks_B=0
heap_tree=peak
Run Code Online (Sandbox Code Playgroud)

如果我们运行valgrind --tool=massif ./a.out 1(如此case 2:严格的代码),在高峰使用时,输出是这样的:

time=2523909
mem_heap_B=120000
mem_heap_extra_B=16
mem_stacks_B=0
heap_tree=peak
Run Code Online (Sandbox Code Playgroud)

注意它mem_heap_extra_B是多么不同- 在第一种情况下,它大于实际的堆使用量(因为每4字节分配实际占用更多),在第二种情况下,额外字节只有16,但实际"使用" "堆的大小是相同的,120000(这是有道理的,我们在8个字节有10000个指针,每个4个字节有10000个整数).

不幸的是,当涉及到堆栈使用时,这个程序相当无趣,但是如果你使用--stacks=yes它,它将显示所使用的堆栈的字节数,例如:

time=2222719
mem_heap_B=120000
mem_heap_extra_B=16
mem_stacks_B=528
Run Code Online (Sandbox Code Playgroud)

如果我mem_stacks_B正在使用的Pascal编译器中进行grep ,那么它会变得更有趣:

 10:mem_stacks_B=0
 18:mem_stacks_B=1576
 26:mem_stacks_B=1368
 34:mem_stacks_B=1368
 42:mem_stacks_B=1576
 50:mem_stacks_B=120
 58:mem_stacks_B=2592
 66:mem_stacks_B=4656
288:mem_stacks_B=2464
296:mem_stacks_B=43104
431:mem_stacks_B=2424
439:mem_stacks_B=10960
447:mem_stacks_B=8096
622:mem_stacks_B=8352
887:mem_stacks_B=3816
895:mem_stacks_B=3360
903:mem_stacks_B=3664
911:mem_stacks_B=3216
Run Code Online (Sandbox Code Playgroud)

还有很多,但足以表明"堆栈使用量变化很大".

如您所见,它有很大差异.不,我没有试图弄清楚当它使用43KB的堆栈时它正在做什么 - 它无论如何都不是真的太离谱了.