草庐IT

c++ - 堆栈内存未释放

coder 2024-02-14 原文

我有以下循环,它从此处的实现中弹出我拥有的 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 并退出循环时,它确实会下降。 (程序还在运行)但是我不能有这个,因为usleep在哪里,我想做一些密集的处理。

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

该结构定义如下,并在程序开始时填充。

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

它填充了约 10000 像素数据,大致相当于 5GB。系统只有~8GB。 因此,释放内存用于系统中的其他处理非常重要。

最佳答案

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

虚拟内存

首先,您需要了解,仅仅因为您的程序“使用”了 5 GB 的内存并不意味着其他程序只剩下 3 GB 的 RAM。虚拟内存意味着这 5 GB 可能只是 1 GB 的实际“驻留”数据,而其他 4 GB 实际上可能在磁盘上而不是在 RAM 中。因此,在查看程序时,查看“驻留集大小”而不是“虚拟大小”很重要。请注意,如果您的系统实际上运行内存不足,操作系统可能会通过“调出”部分内存来缩小某些程序的 RSS。因此,不要太担心系统监视器中出现的“5 GB”——如果您遇到真实、具体的性能问题,请担心。

堆分配

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

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

这里的问题是,在现实世界中,仅仅因为您释放删除 某些内容并不意味着操作系统会立即回收该内存。事实上,它可能无法回收任何未使用的跨度,除非它们处于“末尾”(即最近分配的)。由于 C++ 没有垃圾收集功能,并且未经您的同意不能在内存中四处移动项目,因此您最终会在程序的虚拟内存中遇到这个大“洞”。那个空洞将用于满足 future 的内存分配请求,但如果你没有,它就坐在那里,直到队列完全为空:

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

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

[program]

这会让您回到起点。

解决方案

如果你想“修复”这个问题,一个选择是“反向”分配你的内存,即将分配的最后一个项目放在队列的前面。

另一种选择是通过 mmap 为队列分配元素,例如Linux 将自动执行“大”的分配。您可以通过调用 mallopt(3) 更改此阈值使用 M_MMAP_THRESHOLD 并将其设置为比您的结构大小小一点。这使得分配彼此独立,因此操作系统可以单独回收它们。这种技术甚至可以应用于现有程序而无需重新编译,因此如果您需要在无法修改的程序中解决此问题,这通常很有用。

关于c++ - 堆栈内存未释放,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34283840/

有关c++ - 堆栈内存未释放的更多相关文章

  1. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  2. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  3. ruby-on-rails - Ruby 中的内存模型 - 2

    ruby如何管理内存。例如:如果我们在执行过程中采用C程序,则以下是内存模型。类似于这个ruby如何处理内存。C:__________________|||stack|||------------------||||------------------|||||Heap|||||__________________|||data|__________________|text|__________________Ruby:? 最佳答案 Ruby中没有“内存”这样的东西。Class#allocate分配一个对象并返回该对象。这就是程序

  4. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  5. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  6. 键删除后 ruby​​ 哈希内存泄漏 - 2

    你好,我无法成功如何在散列中删除key后释放内存。当我从哈希中删除键时,内存不会释放,也不会在手动调用GC.start后释放。当从Hash中删除键并且这些对象在某处泄漏时,这是预期的行为还是GC不释放内存?如何在Ruby中删除Hash中的键并在内存中取消分配它?例子:irb(main):001:0>`ps-orss=-p#{Process.pid}`.to_i=>4748irb(main):002:0>a={}=>{}irb(main):003:0>1000000.times{|i|a[i]="test#{i}"}=>1000000irb(main):004:0>`ps-orss=-p

  7. arrays - Ruby 数组 += vs 推送 - 2

    我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“

  8. ruby-on-rails - HTTParty 的内存问题和下载大文件 - 2

    这会导致Ruby出现内存问题吗?我知道如果大小超过10KB,Open-URI会写入TempFile。但是HTTParty会在写入TempFile之前尝试将整个PDF保存到内存吗?src=Tempfile.new("file.pdf")src.binmodesrc.writeHTTParty.get("large_file.pdf").parsed_response 最佳答案 您可以使用Net::HTTP。参见thedocumentation(特别是标题为“流媒体响应机构”的部分)。这是文档中的示例:uri=URI('http://e

  9. += 的 Ruby 方法 - 2

    有没有办法让Ruby能够做这样的事情?classPlane@moved=0@x=0defx+=(v)#thisiserror@x+=v@moved+=1enddefto_s"moved#{@moved}times,currentxis#{@x}"endendplane=Plane.newplane.x+=5plane.x+=10putsplane.to_s#moved2times,currentxis15 最佳答案 您不能在Ruby中覆盖复合赋值运算符。任务在内部处理。您应该覆盖+,而不是+=。plane.a+=b与plane.a=

  10. ruby - Sinatra + Heroku + Datamapper 使用 dm-sqlite-adapter 部署问题 - 2

    出于某种原因,heroku尝试要求dm-sqlite-adapter,即使它应该在这里使用Postgres。请注意,这发生在我打开任何URL时-而不是在gitpush本身期间。我构建了一个默认的Facebook应用程序。gem文件:source:gemcuttergem"foreman"gem"sinatra"gem"mogli"gem"json"gem"httparty"gem"thin"gem"data_mapper"gem"heroku"group:productiondogem"pg"gem"dm-postgres-adapter"endgroup:development,:t

随机推荐