【问题标题】:XCode/Instruments not showing memory leaksXCode/Instruments 未显示内存泄漏
【发布时间】:2011-10-10 12:07:57
【问题描述】:

我正在关注斯坦福 iOS 开发讲座,并且我有一个计算器大脑课程,它在控制器中是 alloc init,但我没有在 deallocreleased。

- (CalculatorBrain *)brain
{
    if (!brain) 
        brain = [[CalculatorBrain alloc] init];

    return brain;

}

我从 XCode 运行 -> 使用性能工具运行,应用程序启动并且没有出现泄漏,然后我在 iOS 模拟器中单击主页按钮,但什么也没有,然后我双击主页按钮并关闭应用程序,但仍然没有。

我也做了构建和分析,但没有发现任何东西

你能告诉我为什么它不捡起来吗?

【问题讨论】:

  • 你的第一句话毫无意义。可以修改一下吗?
  • 你在使用带有自动引用计数的 XCode 4.2 吗?
  • 不,我使用的是 XCode 3.2.6
  • main 中是否有自动释放池。
  • 有。你能解释一下它是如何工作的吗?它是一个庞大的包装器来整理东西,因此您不必担心 dealloc 等(并不是说我不会正确地进行内存管理)

标签: objective-c ios xcode instruments


【解决方案1】:

看起来好像没有可检测到的泄漏。看这一行:

brain = [[CalculatorBrain alloc] init];

只要brain 指向一个对象,该对象就不会被视为“内存泄漏”。如果你在某个时候这样做,

brain = nil;

然后泄漏将被注册。释放容器对象也可以实现这一点,但您确定它正在被释放吗? (例如,当您的程序退出时,它不会被释放。)

问题:泄漏检测器不能检测所有内存泄漏——这是一个数学证明的事实。大多数检测器只检测无法到达的对象,并且许多泄漏检测器特别容易出现误报——在 C 中,很难在运行时区分指针和整数。

编辑:听起来您的应用程序只创建了一个控制器实例,而控制器只创建了一个CalculatorBrain 实例。如果您考虑真正的内存泄漏是什么,您可以将其定义为您的程序不会释放回操作系统的未使用内存。

  • 当程序运行时,CalculatorBrain 一直在使用,因此它不是泄漏。
  • 当程序退出时,操作系统会自动回收你的进程使用的所有内存,因此程序退出后不会有任何内存泄漏。

如果您想创建泄漏以查看其外观,您可以在程序运行时多次创建新的CalculatorBrain,但忘记释放未使用的版本。在这种情况下,随着您的程序运行,越来越多的CalculatorBrain 实例将累积。在 iOS 和其他嵌入式系统上,这通常会使您的程序崩溃。在现代 64 位计算机上,它会逐渐填满可用的交换空间,直到您用完交换空间、地址空间或其他一些资源——导致程序崩溃或使系统非常无响应。

标准做法是不关心释放整个程序运行时应该存在的对象。

【讨论】:

  • 容器对象是指调用 alloc & init 的类/对象吗?
  • @Jon:我说的是具有“大脑”实例变量的实例。 (我不应该使用“容器”,因为这个词真的有别的意思。)
  • 谢谢。但是,我只有一个带有大脑的控制器。如果它设置为 nil 并且应用程序退出,它不会整理它吗?根据这个问题*.com/questions/2075069/… 它会。你的回答说不会……
  • @Jon:设置什么为零?当我说“解除分配”时,我实际上是指 dealloc 方法。
  • 在你的回答中你说brain = nil;如果已编码并且应用程序退出,是否会出现内存泄漏?
【解决方案2】:

分析器无法找到所有内存泄漏。就它而言,将实例存储到 ivar 中不会从该方法中泄漏它,然后在 dealloc 中它没有意识到应该释放 ivar。 XCode 4 可能在这方面有所改进,我不记得了(我自己仍然使用 XCode 3)。

至于性能工具,请记住一个对象不会被认为是泄漏的,直到不再有对它的引用。因此,即使您的控制器没有释放大脑,在控制器被释放(或接受大脑移植)之前,大脑也不会被视为泄漏。另外,请注意,在 *nix-like 系统上,内存分配会在进程退出时自动清理。因此,如果您为进程生命周期内应该存在的对象(例如应用程序委托及其永久保留的任何内容)分配内存并依赖此行为在进程退出时释放它,这并不是真正的泄漏。

【讨论】:

    【解决方案3】:

    嗯...确实泄漏无法检测到所有内存泄漏,但假设您正在这样做:

    myIvarBrain=[self brain];
    

    如果您将它提供给 iVar(在您的类的 dealloc 中发布,并且没有访问器),实际上根本没有泄漏。返回的 RC 是 1,并且自从你的类被释放后它将是 1。如果你不在 dealloc 中释放它,你应该等待你的类的 dealloc 来查看内存泄漏。 有意义吗?

    【讨论】: