XCode/Instruments没有显示内存泄漏

9

我正在跟随斯坦福iOS开发讲座学习,并且有一个计算器脑部类,它已经在控制器中进行了alloc init,但是我没有在dealloc中进行release

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

    return brain;

}

我从XCode中运行了性能测试工具,应用程序启动并没有出现任何泄漏。然后我在iOS模拟器中点击了主屏幕按钮,但是没有反应。接着我双击主屏幕按钮关闭了应用程序,但仍然没有反应。
我还进行了“构建和分析”,但它没有发现任何问题。请问为什么它没有检测到问题?

你的第一句话没有意义。你能否请编辑一下? - csano
你正在使用带有自动引用计数的XCode 4.2吗? - albertamg
不,我正在使用XCode 3.2.6。 - Jon
主函数中有自动释放池吗? - user523234
有的。你能解释一下它是如何工作的吗?它是一个大型包装器来整理东西,因此您不必担心dealloc等(尽管我会正确地进行内存管理)。 - Jon
3个回答

7

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

brain = [[CalculatorBrain alloc] init];

只要brain指向一个对象,那么该对象不会被视为"内存泄漏"。如果您在某个时刻执行以下操作:
brain = nil;

然后内存泄漏将会被注册。虽然释放容器对象也能实现这个目的,但是你确定它正在被释放吗?(例如当你的程序退出时,它不会被释放。)
问题是:泄漏检测器不能检测所有内存泄漏——这是一个经过数学证明的事实。大多数检测器只检测无法访问的对象,并且许多泄漏检测器尤其容易出现假阴性——在C中,在运行时很难区分指针和整数。
编辑:听起来您的应用程序只创建控制器的一个实例,该实例仅创建 CalculatorBrain 的一个实例。如果您思考一下内存泄漏的真正含义,您可以将其定义为您的程序未释放回操作系统的未使用内存。
  • 当程序正在运行时, CalculatorBrain 始终在使用,因此它不是泄漏。
  • 当程序退出时,操作系统会自动回收进程使用的所有内存,因此在程序退出后不可能有任何内存泄漏。
如果您想创建一个内存泄漏以查看其外观,可以在程序运行时多次创建新的 CalculatorBrain ,但忘记释放未使用的版本。在这种情况下,随着程序运行,会累积越来越多的 CalculatorBrain 实例。在iOS和其他嵌入式系统上,这通常会导致程序崩溃。在现代64位计算机上,它将逐渐填满可用的交换空间,直到您耗尽交换、地址空间或其他一些资源——导致程序崩溃或使系统非常不响应。
标准做法是不必担心为整个程序运行而存在的对象进行解除分配。

你所说的容器对象是指调用alloc和init的类/对象吗? - Jon
@Jon:我在谈论具有“brain”实例变量的实例。(我不应该使用“container”,因为那个词确实意味着其他东西。) - Dietrich Epp
谢谢。但是我只有这一个带有控制器的大脑。如果将其设置为nil并退出应用程序,它不会被清理吗?根据这个问题http://stackoverflow.com/questions/2075069/iphone-delegate-controller-dealloc 的回答会这样做。您的答案说不会... - Jon
@Jon:将什么设置为nil?当我说“释放”时,实际上是指特定的dealloc方法。 - Dietrich Epp
在你的回答中,你说brain = nil; 如果这样编码并且应用程序退出,会有内存泄漏吗? - Jon
@Jon:理论上,如果您在不调用对象的release方法的情况下将ivar brain设置为nil,并且没有其他可访问的引用指向brain,那么可能(但不保证)会被泄漏检测器检测到泄漏。 - Dietrich Epp

0

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

myIvarBrain=[self brain];

如果您将其分配给一个iVar(在类的dealloc中释放,且没有访问器),实际上根本没有泄漏。返回的RC为1,并且自类的解除分配以来一直为1。如果您在dealloc中不释放它,则应等待类的dealloc以查看内存泄漏。

有意义吗?


0
分析器无法找到所有的内存泄漏。就它而言,将实例存储到ivar中并不会从该方法中泄漏它,然后在dealloc中它也没有意识到ivar应该被释放。XCode 4 在这方面可能有所改进,我不记得了(我仍然使用XCode 3)。
至于性能工具,请记住,只有当没有任何东西持有对对象的引用时,该对象才被认为是泄漏的。因此,即使您的控制器不释放大脑,只要控制器被释放(或接受了大脑移植),大脑就不会被认为是泄漏的。此外,请注意,在*nix类系统上,内存分配会在进程退出时自动清除。因此,如果您为应该存在于进程生命周期中的对象(例如应用程序委托和它永久持有的任何内容)分配内存,并依赖于此行为在进程退出时释放它,则它并不是真正的泄漏。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接