当前位置:  开发笔记 > 编程语言 > 正文

堆栈内存未释放

如何解决《堆栈内存未释放》经验,为你挑选了1个好方法。

我有以下循环,它弹出一个C++并发队列,来自这里的实现.https://juanchopanzacpp.wordpress.com/2013/02/26/concurrent-queue-c11/

while (!interrupted)
{
    pxData data = queue->pop(); 
    if (data.value == -1)
    { 
        break; // exit loop on terminating condition
     }
    usleep(7000); // stub to simulate processing
}

我正在使用CentOS7中的系统监视器查看内存历史记录.我正在尝试从队列中读取值后释放队列占用的内存.但是,随着以下while循环运行,我看不到内存使用率下降.我已经确认队列长度确实下降了.

但是,当遇到-1并且循环退出时,它确实会下降.(程序仍在运行)但是我不能拥有这个,因为在我们睡觉的时候,我想做一些密集的处理.

问题:为什么数据占用的内存不能自由编辑?(根据系统监视器)当变量超出范围时,堆栈分配的内存是不是应该被释放?

结构定义如下,并在程序开头填充.

typedef struct pxData
{
  float value; // -1 value terminates the loop
  float x, y, z;
  std::complex valueData[65536];
} pxData;

它填充了~10000 pxData,大致翻译为5GB.系统只有~8GB.因此,为了在系统中进行其他处理,内存可以自由编辑.



1> John Zwinck..:

这里有一些事情在起作用.

虚拟内存

首先,您需要了解,仅仅因为您的程序"使用"5 GB的内存并不意味着其他程序只剩下3 GB的RAM.虚拟内存意味着那些5 GB可能只有1 GB的实际"驻留"数据,而另外4 GB实际上可能在磁盘而不是RAM中.因此,当您查看程序时,查看"常驻设置大小"而不是"虚拟大小"非常重要.请注意,如果您的系统实际上在RAM上运行不足,操作系统可能会通过"分页"部分内存来缩小某些程序的RSS.因此,不要过于担心系统监视器中出现"5 GB" - 如果您遇到真正的具体性能问题,请担心.

堆分配

第二个方面是您从队列中删除项目时虚拟大小不会减少的原因.我们可以猜测,您可以通过使用mallocnew逐个创建它们将这些元素放入队列,然后将它们推送到队列的后面.这意味着您分配的第一个元素将首先从队列中出来.而这反过来意味着当你耗尽了90%的队列时,你的内存分配可能如下所示:

[program|------------------unused-------------------|pxData]

这里的问题是,在现实世界中,仅仅因为你free或者delete其他东西并不意味着操作系统会立即回收那些记忆.实际上,它可能无法回收任何未使用的跨度,除非它们处于"结束"(即最近分配的).由于C++没有垃圾收集,并且在未经您同意的情况下无法在内存中移动项目,因此您最终会在程序的虚拟内存中出现这个"漏洞".该漏洞将用于满足未来的内存分配请求,但如果您还没有,它只是坐在那里,直到队列完全为空:

[program|------------------unused--------------------------]

然后系统能够缩小您的虚拟地址空间:

[program]

这将带您回到您的起点.

解决方案

如果你想"修复"这个,一个选择是以"反向"分配你的内存,即将最后的项目分配到队列的前面.

另一个选择是为队列分配元素mmap,例如Linux将自动执行"大"的分配.您可以通过调用改变这个门槛mallopt(3)M_MMAP_THRESHOLD和设置它比你的结构尺寸小一点点.这使得分配彼此独立,因此OS可以单独回收它们.这种技术甚至可以应用于现有程序而无需重新编译,因此如果您需要在无法修改的程序中解决此问题,通常很有用.

推荐阅读
赛亚兔备_393
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有