我正在使用OS X 10.5.6。我有一个带有Qt的GUI的C ++应用程序。当我启动我的应用程序时,它使用30 MB内存(由OS X活动监视器RSIZE报告)。
我使用此应用程序将文本文件读入内存,解析数据并最终将其可视化。如果我打开(读取内存,解析,可视化)9 MB文本文件,活动监视器报告我的应用程序从最初的30 MB内存增长到103 MB。
现在,如果关闭文件并删除已解析和可视化的数据,则应用程序的大小将保持为103 MB。这听起来像是一个内存泄漏给我。但是如果我再次打开文件,将其读取到内存,解析它并将其可视化,应用程序将保持在103 MB。无论我打开文件多少次(或相同大小的另一个文件),我的应用程序内存使用都会保持不变。这是否意味着它不是内存泄漏?如果是泄漏,那么每次打开文件时内存使用量应该会不断增长吗?它增长的唯一时间是我打开一个比前一个更大的文件。
这是正常的吗?这个平台或库是否依赖?这是由操作系统或库完成的某种缓存吗?
答案 0 :(得分:2)
这似乎相对正常,但所有操作系统都略有不同。
在通常的应用程序生命周期中,应用程序从OS请求内存,并以其管理的大块(通过C / C ++标准库)提供内存。当应用程序获取/释放内存时,这一切都是在应用程序内部完成的,无需借助操作系统,直到应用程序没有离开,然后再向操作系统调用另一个大块。
在应用程序退出之前,内存通常不会返回到操作系统(尽管大多数操作系统确实提供了在需要时执行此操作的机制,并且某些C / C ++标准库将使用此工具)。应用程序使用已经给出的所有内容并进行自己的内存管理,而不是将内存返回给操作系统。
虽然注意:仅仅因为应用程序有内存并不意味着它正在占用芯片上的RAM。偶尔使用或暂时未使用的内存将暂时保存到二级/三级存储中。
活动监视器:检查内存使用情况不是一个非常有用的工具,因为您发现它只显示实际分配给应用程序的总数。它不显示有关应用程序如何内部分配此内存的任何信息(大多数可以解除分配)。检查XCode所在的文件夹,有一套广泛的工具可用于检查应用程序如何与开发环境一起工作。
注意:我已经避免使用像页面等术语,因为这些与C / C ++ / Objective C没有任何关系,并且都是特定于操作系统/硬件的。
答案 1 :(得分:2)
这听起来像是一个内存碎片问题。内存是从页面中的OS获取的。页面通常是几KB大,例如4 kB。现在,如果您为对象分配100 MB RAM,则内存分配器(new / malloc)会向操作系统请求许多可用内存页并在其上分配对象。当您的应用程序完成计算并删除某些时,即使是大多数(但不是所有以前分配的对象),未删除的对象都会保留页面并禁止将它们返回给操作系统。仅当所有其内存被释放时,才能返回页面。因此,在极端情况下,8B对象可以阻止返回完整的4kB页面。
操作系统通过计算提交到应用程序的页数来报告内存消耗,而不是通过计算对象在这些页面上占用的空间。因此,如果您的内存碎片化,页面将保持提交状态,并且报告的内存消耗保持不变。
内存消耗在第二次运行时不会增长,因为在第二次运行时,分配器重用,以前获得的,主要是空闲页面。
碎片问题的解决方案通常是预先分配更大的内存块,并使用自定义内存分配器从这个更大的块中分配具有相似生命周期的对象。然后,当您完成对象时,删除整个块。
另一种解决方案是切换到完全垃圾收集的环境,如Java或.NET - 它们具有压缩垃圾收集器,可以防止此类问题。