【问题标题】:Why Does a Memory Leak not Continue after Peaking?为什么达到峰值后内存泄漏不会继续?
【发布时间】:2012-04-02 16:14:25
【问题描述】:

我故意制造了一个内存泄漏来向即将学习指针的人展示一个点。

int main()
{
    while (1)
    {
        int *a = new int [2];
        //delete [] a;
    }
}

如果在没有注释代码的情况下运行,内存将保持低位并且不会像预期的那样上升。但是,如果按原样运行,那么在具有 2GB RAM 的机器上,内存使用量会迅速上升到大约 1.5GB,或者系统未使用的任何东西。但是,一旦达到这一点,CPU 使用率(以前是最大值)就会大大下降,内存使用率也会下降到大约 100MB。

究竟是什么导致了这种干预动作(如果有比“Windows”更具体的东西,那就太好了),为什么程序不占用它循环的 CPU,但也不终止?它似乎卡在循环结束和 main 结束之间。

Windows XP、GCC、MinGW。

【问题讨论】:

  • 您如何测量“内存使用率”和“CPU 使用率”?您的测量设备是否可能正在测量工作集大小或物理内存大小而不是虚拟内存大小?
  • 我使用的是默认任务管理器。
  • “干预动作”可能是由于某些处理程序捕获的崩溃而您看不到它,并且在崩溃后执行清理。
  • “我正在使用默认任务管理器。”这报告了很多信息。你用的是什么数据?
  • 我只是使用带有内存使用和 CPU 使用列的进程选项卡。但是,添加虚拟内存实际上表明虚拟内存继续上升。不过,我仍然不确定物理内存会发生什么。此外,添加一个包含所有异常的 try-catch 不会产生任何结果。

标签: c++ windows memory-leaks


【解决方案1】:

可能发生的情况是您的代码分配了所有可用的物理 RAM。当它达到该限制时,系统开始在交换文件上为其分配空间。这意味着它(几乎)一直在磁盘上等待,因此它的 CPU 使用率下降到(几乎)为零。

系统可能很容易跟踪它从未真正写入它分配的内存的事实,因此当它需要存储在交换文件中时,它只会做一个小记录基本上是说“进程 X 有 N 个字节的未初始化存储”,而不是实际将所有数据复制到硬盘驱动器(但我不确定,这很可能取决于您使用的确切系统)。

【讨论】:

  • 确实如此。我知道虚拟内存以及它如何导致极度缓慢。我不知道它实际上试图移动这么多。 CPU 使用率的解释听起来也很合理。
  • 它在 2GB 左右失败,表明物理地址空间是一个限制因素(即 32 位 XP)。
【解决方案2】:

套用 Inigo Montoya 的话说,“我不认为这意味着你认为那意味着什么。” Windows 任务管理器不显示您正在查找的内存使用数据。

“Mem Usge”列显示与进程的工作集大小(或驻留集大小)相关的内容。也就是说,“Mem Usage”显示一个与当前分配给您的进程的物理内存量相关的数字。

“VM Size”列显示一个与虚拟内存子系统完全无关的数字(它实际上是进程分配的私有堆的大小。

尝试使用不同的工具来查看虚拟内存使用情况。我建议Process Explorer

【讨论】:

  • 其实我在家里确实用过进程资源管理器,但是我总是不习惯任务管理器的设计,而且我也不经常使用任务管理器独有的功能。
【解决方案3】:

我猜当程序耗尽可用的物理内存时,它开始使用磁盘(虚拟)内存,它变得如此缓慢,看起来好像它是不活动的。尝试添加一些速度可视化:

int counter = 0;
while (1)
{
    int *a = new int [2];
    ++counter;
    if (counter % 1000000 == 0)
        std::cout << counter << '\n'
}

【讨论】:

    【解决方案4】:

    XP任务管理器中默认的Memory列是进程工作集的大小(分配给该进程的物理内存量),而不是实际的内存使用量。

    http://msdn.microsoft.com/en-us/library/windows/desktop/ms684891%28v=vs.85%29.aspx

    http://blogs.msdn.com/b/salvapatuel/archive/2007/10/13/memory-working-set-explored.aspx

    【讨论】:

      【解决方案5】:

      任务管理器的“内存使用”列可能是“工作集”,正如question 中的一些答案所解释的那样,尽管老实说,我仍然对任务管理器如何在内存更改时引用内存感到困惑从版本到版本。该值上升/下降,因为您显然在任何给定时间实际上都没有使用太多内存。如果您查看“VM 大小”,您应该会看到它不断增加,直到发生不好的事情。

      您也可以尝试Process Explorer,我发现它的显示方式很容易理解。

      【讨论】:

        【解决方案6】:

        有几件事:首先,如果您一次只分配 2 个ints,它 可能需要几个小时才能注意到总内存使用量正在上升 因为它。其次,在很多系统上,分配不 提交直到您实际访问内存;地址空间可能是 保留,但你并没有真正的记忆(并且程序将 如果您尝试访问内存并且没有可用内存,则会崩溃。

        如果你想模拟泄漏,我建议至少分配一个页面 一次,如果不是更多,并且至少写入一个字节 每个分配的页面。

        【讨论】:

        • 嗯,这是一个无情的循环。该循环每秒执行很多次。即使只是使用1,我也看到我眼前的内存增加了很多。
        猜你喜欢
        • 2011-10-25
        • 2016-12-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-12-19
        • 2013-07-12
        相关资源
        最近更新 更多