【问题标题】:Resident memory behaviour in this programme?这个程序中的常驻记忆行为?
【发布时间】:2014-06-22 23:28:17
【问题描述】:

我正在处理常驻内存增加问题。 为了模拟我写了一个代码sn-p,它实际上是在模拟我的问题。

#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <malloc.h>
using namespace std;

int main()
{
    int  count = 0;
    char szCmd[128];

    system("> result_top.txt");

    while (count < 10)
    {
        sprintf(szCmd, "echo \"\nRound %d\n\" >> result_top.txt", count);
        system(szCmd);

        system("top -b -n 1 -p `pgrep a.out` | tail -4 >> result_top.txt");

        int **t = new int*[100000];

        for(long i = 0; i < 100000; i++)
        {
            t[i] = new int();
        }

        system("top -b -n 1 -p `pgrep a.out`| tail -4 >> result_top.txt");

        for(long i = 100000 - 1; i >= 0; i--)
        {
            delete t[i];
        }

        delete [] t;

        sleep(5);

        system("top -b -n 1 -p `pgrep a.out`| tail -4 >> result_top.txt");
        printf("round %d finished\n", count);
        count++;
    }

    return 0;
}

现在我在每一轮之后记录常驻内存并将其重定向到文件 result_top.txt 中。 这是文件 result_top.txt 中的 o/p

Round 0

/* Before Allocation RES */
  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
11053 root      20   0 11736  852  724 S  0.0  0.0   0:00.00 a.out

/* After allocation RES */
  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
11053 root      20   0 15688 4808  768 S  0.0  0.2   0:00.01 a.out

/* After Deletion RES*/
  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
11053 root      20   0 14904 4028  772 S  0.0  0.2   0:00.02 a.out


Round 1


  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
11053 root      20   0 14908 4048  788 S  0.0  0.2   0:00.02 a.out


  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
11053 root      20   0 15700 4828  788 S  0.0  0.2   0:00.05 a.out


  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
11053 root      20   0 11872 1052  788 S  0.0  0.0   0:00.06 a.out

Round 2


  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
11053 root      20   0 11872 1052  788 S  0.0  0.0   0:00.06 a.out


  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
11053 root      20   0 15688 4828  788 S  0.0  0.2   0:00.08 a.out


  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
11053 root      20   0 11872 1052  788 S  0.0  0.0   0:00.09 a.out


Round 3


  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
11053 root      20   0 11872 1052  788 S  0.0  0.0   0:00.09 a.out


  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
11053 root      20   0 15688 4828  788 S  0.0  0.2   0:00.11 a.out


  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
11053 root      20   0 11872 1052  788 S  0.0  0.0   0:00.13 a.out

现在在第 0 轮中,当我释放内存时,驻留内存为 4028,而在分配内存之前的第二次迭代中,它变为 4048。

增加了 20 个字节

在第一轮之后,每一轮一切都很好。那么这 20 字节增加的原因是什么?

类似的情况也发生在我的项目代码中。

【问题讨论】:

  • 我建议使用外部工具来查看进程的内存消耗。在顶部测量之间,例如你打电话给 printf/sprintf/system 谁知道他们在内部做什么。还要记住,在 malloc 实现决定这样做之前,RES 可能不会减少。只是调用 delete() 并不意味着 RES 会下降。对于工具,我建议使用 valgrind 的地块或类似的东西:milianw.de/code-snippets/tracking-memory-consumption-using-pmap欢呼

标签: c++ memory-management memory-leaks operating-system


【解决方案1】:

我自己拿了这段代码并执行了。 我想您在第 0 轮之后看到的 20 字节增加是因为尚未遇到的代码部分。因此它还没有映射到常驻内存。 现在什么时候会遇到这个新代码,它会被映射到常驻内存中。

所以你看到的 20 字节会增加。

要识别这一点,您可以删除上次顶部记录后新遇到的代码并检查常驻内存,20k 不会有记录器。

【讨论】:

    【解决方案2】:

    我不知道具体为什么会看到这种效果,但请注意操作系统不负责实现新/删除功能。操作系统提供的唯一帮助是更改分配给进程的总内存大小(通常在 Unix-ish 系统上通过 brk()/sbrk() 请求)。

    因此,您看到的明显泄漏与 new/delete 的具体实现有关。在第二次删除调用中满足条件之前,这些可能不是“垃圾收集”未使用的内存。在他们达到这一点并要求减少分配给进程的总内存大小之前,您无法观察到内存现在可以从 top 之类的工具中释放出来。

    在某种程度上,这是内存泄漏,因为空闲内存没有尽快返回给操作系统。但是,您可能相信 new/delete 实现应该以合理的方式释放内存,以避免过度浪费内存。

    在 C++ 中,如果默认值不适合您的需要,您可以更改 new/delete 的实现...

    【讨论】:

      猜你喜欢
      • 2016-09-18
      • 1970-01-01
      • 2016-01-18
      • 2016-04-18
      • 2017-02-25
      • 2023-04-06
      • 1970-01-01
      相关资源
      最近更新 更多