Objective c 内存未完全释放

Objective c 内存未完全释放,objective-c,automatic-ref-counting,Objective C,Automatic Ref Counting,我第一次开始使用SceneKit、SpriteKit和ARC创建一个应用程序。我注意到,当我在不同的视图之间切换时,内存使用量迅速增加。我的第一个想法是我有内存泄漏,但我现在不确定。这种行为甚至出现在这个基本示例中: for(int r=0;r<9999999;r+=1){ NSString *s=[NSString stringWithFormat:@"test%i",r]; s=nil; } for(int r=0;r 不要依赖NSString进行内存诊断。它具有相当

我第一次开始使用SceneKit、SpriteKit和ARC创建一个应用程序。我注意到,当我在不同的视图之间切换时,内存使用量迅速增加。我的第一个想法是我有内存泄漏,但我现在不确定。这种行为甚至出现在这个基本示例中:

for(int r=0;r<9999999;r+=1){
    NSString *s=[NSString stringWithFormat:@"test%i",r];
    s=nil;
}
for(int r=0;r
  • 不要依赖
    NSString
    进行内存诊断。它具有相当非典型的行为

    这是一个并不少见的场景,我在S.O.上见过不止一次,为了将一些复杂的内存问题简化为更简单的问题,开发人员使用
    NSString
    创建了一个简化的示例,但没有意识到选择特定的类会引入奇怪的、不相关的行为。新的“调试内存图”工具或久经考验的工具(下面讨论)是诊断代码中潜在问题的最佳方法

  • 另一方面,您谈论的是立即释放对象。如果您的方法不是以
    alloc
    new
    copy
    mutableCopy
    开始的,则返回的对象在超出范围后不会立即释放,因为它们是
    自动释放
    对象。直到autorelease池已排空(例如,您退回运行循环)

    这样,如果你的应用程序的“高水位”标志太高,但是内存最终回到可接受的水平,那么考虑自动选择对象的选择(和/或引入你自己的自动存储池)。但通常,这种自动释放与非自动释放对象的区别有些学术性,除非您有一个非常长的运行循环,在该循环中,您在返回运行循环之前分配了许多对象

    简而言之,自动释放对象不影响对象是否被释放,而只影响对象被释放的时间。我提到这一点只是为了回应大型
    for
    循环和对象应立即被释放的争论。自动释放对象的存在会影响释放的精确时间

  • 关于应用程序内存的快速增长,这可能与您的示例完全无关。诊断方法是使用仪器(如WWDC 2013中所述)。简而言之,选择“产品”-“配置文件”并选择“泄漏”工具(这也将抓住基本的“分配”工具),练习应用程序,然后精确查看分配和未发布的内容

    另外,Xcode 8的“调试对象图”该工具也非常有用,甚至更易于使用。WWDC 2016中介绍了该工具。使用该工具,您可以在左侧面板中看到对象列表,当您选择一个对象时,您可以看到与该对象关联的对象图,因此您可以诊断您可能仍然有哪些未解析的引用:

  • 顺便说一下,您可以尝试模拟内存警告。Cocoa对象执行各种缓存,其中一些在内存压力下被清除

  • 如果在方案上启用了任何内存调试选项(例如,僵尸),请注意,这些选项会在捕获关联的调试信息时导致额外的内存增长。在分析泄漏、废弃或缓存的内存之前,您可能希望关闭任何调试选项


  • 总之,如果每次迭代都有几kb的增长,并且实例化的对象都没有出现,并且没有任何调试选项处于打开状态,那么您可能不需要担心。许多Cocoa对象正在进行各种各样的缓存,这超出了我们的控制范围,通常可以忽略不计。但是如果内存不足每次迭代增加mb或gb(不必担心第一次迭代,只需担心后续迭代),那么这就是您真正需要仔细研究的内容。

    1.NSString只是为了简单起见选择的一个示例。在我的应用程序中,我最初在自定义SceneKit视图中使用了相同的示例。该示例的结果与此行相同:SCNScene*s=[SCNScene scene scene];2.这可能就是我想要的。我将进一步探讨这个主题。3.我已经在使用这些工具,它们使查找未发布的对象变得非常容易。这就是我如何将我的观察精简到这个短循环示例的原因。但是,这些NSString或SCNScene没有列出,它们仍然占用一些内存。请注意t我的例子完全是人为的。循环在那里,因此它增加了大量内存。我并没有真正遇到问题,但我注意到在视图之间来回切换时,内存使用量在增加。我知道这听起来像是有漏洞,但我的项目仍然几乎是空的。我想修复或理解这一点在项目变得更复杂之前。你可以将这个带有NSString或SCNScene的示例循环添加到一个空的新项目中,它仍然会消耗内存,而应该全部释放。这就是我想了解的。顺便说一句,你可以试着模拟内存压力。Cocoa对象会进行各种缓存,其中一些缓存在有备忘录时会被清除另外,如果您打开任何内存调试选项(特别是僵尸),则在您的方案中,请注意这些会导致额外的内存增长,您可能希望在分析泄漏的、废弃的或缓存的内存之前关闭这些。感谢您帮助我解决此问题。我没有打开僵尸,但您的建议使我关闭了所有调试设置,从而解决了此问题。因此,此问题与deb有关ugging features.非常好。我在下面的回答中加入了这一点。“模拟内存警告”在这种情况下没有帮助,在我尝试的示例中,它只释放了1MB或更少的内存。即使是简单的示例,也可能有自动释放池。这里可能没有,但您可能会感到惊讶。
    for(int r=0;r<999999;r+=1){
        SCNNode *tn=[SCNNode node];
        tn=nil;
    }