【问题标题】:iPhone why am i leaking an object?iPhone 为什么我会泄漏一个对象?
【发布时间】:2011-03-09 11:00:40
【问题描述】:

我正忙于一个 iPhone 应用程序。我已经阅读了很多关于内存管理的内容,并且我认为我已经很好地涵盖了。但是当我运行泄漏时,它显示我正在泄漏内存,尽管我认为我没有。

代码如下:


UIButton * plus = [[UIButton buttonWithType:UIButtonTypeRoundedRect] retain];
[plus setTitle:@"+" forState:UIControlStateNormal];
[plus addTarget:self action:@selector(plusClicked:) forControlEvents:(UIControlEvents)UIControlEventTouchDown];
plus.frame = CGRectMake(x+35, y-30, 35, 30);
plus.tag = i;
[self.view addSubview: plus];
[plus release];

(x/y/i 变量等...在上面定义,与此代码无关)。

根据仪器/泄漏,任何人都可以解释为什么我要泄漏 plus 对象吗?

【问题讨论】:

    标签: iphone memory uibutton memory-leaks


    【解决方案1】:

    1) 没有足够的信息可以确定,但我猜这是因为您的控制器实例(或它的视图)正在泄漏,因为在[plus release] 之后,此按钮的唯一所有者是控制器的视图。

    2) 您不必保留自动释放的对象以在本地范围内使用它们 - 它们可以保证在自动释放池耗尽之前存活(在您的情况下发生在事件处理结束时)。

    【讨论】:

    • 1) 没有足够的信息可以确定,但我猜这是因为您的控制器实例(或它的视图)正在泄漏,因为在 [plus release] 之​​后,此按钮的唯一所有者是控制器的视图. >> 正确.. 稍后我将释放这个对象,并且 [super dealloc] 被调用 + 其他一些清理.. 那不应该泄漏吗?
    • 你确定你的控制器的dealloc 真的被调用了吗? “我正在释放这个对象”对我来说听起来很可疑 - 我希望你不要直接打电话给 dealloc,不是吗?
    • 哈哈不,当然不是! ;) 我在 dealloc 中有一个 NSLog(它在每个 dealloc 中只是为了了解事情的来龙去脉,这对我的学习过程有好处)并且当我释放该对象时它会打印出来。所以对话框被整齐地释放了..
    • 好吧,没有代码我可以考虑两种方法来找到错误:1)在你的代码中找到plus的所有条目,并仔细考虑每种情况下的内存管理2)实现临时子类UIButton 和重载 retainreleaseautorelease。除了按钮分配 - [MyTempButton buttonWithType:UIButtonTypeRoundedRect],不要更改代码中的任何内容。使用此方法和调试器中的断点,您可以以 0.999 的概率找到罪魁祸首(保留此按钮但不释放它的对象)。
    • 我已经尝试过第一种情况(所有使用加号的地方都可以在我的代码 sn-p 在此页面上看到),但(不幸的是)不起作用。第二个似乎是一种可能性,但肯定是最后的手段,因为这需要一些(恕我直言丑陋的)工作来修复这么小的项目;)
    【解决方案2】:

    这段代码在加号按钮上保留了三次。一次创建按钮,一次显式,一次在 addSubView: 中。

    此代码还会自动释放加号按钮一次,然后释放一次。 (正如其他答案中提到的,显式保留/释放调用是不必要的,但要平衡,因此不会导致泄漏。)要么你没有平衡addSubView: 中的保留与释放,要么自动释放池没有耗尽。一种可能的解决方案是在释放包含视图之前向 plus 对象发送 release(或可能是 removeFromSuperview)消息。另一种可能的解决方案是确保在此代码运行耗尽时自动释放池处于活动状态。只是为了测试,你可以在你的代码之前添加一个NSAutoreleasePool,然后用类似这样的东西排空池:

    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    
    // your code
    
    [pool release];
    

    如果这样可以解决问题,请检查代码结构以找出自动释放池没有耗尽的原因。

    【讨论】:

    • 你说我发布了两次,一次是自动发布,一次是“硬”发布。最后一次发布应该是当我解除分配父视图时,它应该删除所有子视图,并通过这样做向所有子视图发送释放(因为保留者应该在某个时候释放)。我的问题是为什么最后一个版本没有发生。在我看来,“removeFromSuperView”应该是不必要的,因为父视图应该在解除分配中执行此操作。另外,我必须保留对那个加号按钮的引用,这不应该是.. autoreleasepool 也可能是一个解决方案,但我想了解为什么会发生这种情况
    • 你是对的,一个简单的发布就足够了。 removeFromSuperview 将导致发布,但可能超出要求。您是否在视图的 dealloc 方法中释放加号按钮对象?
    • 不,我没有得到对 plus 对象的引用,我也不想。它只是在该方法的范围内,它必须留在那里,在我看来,该对象中不需要引用,在我完成创建和添加到视图之后,我不需要关心它。如果我会按照你的路径,我应该手动删除我视图中的所有对象,并通过这样做保留对屏幕上所有对象的引用......我是对的吗?
    • 您确实需要在调用 addSubview 时平衡保留。由于我只看到您系统中的这个小窗口,我不确定在哪里平衡保留调用和释放。此外,您确实在视图的 deallocate 方法中引用了 plus 对象。它在视图的 subviews 属性中。
    • 啊,我不知道,对不起!但我想知道为什么iOS在关闭视图时不删除对象,因此这样做也会释放它。我认为这就是iOS框架的全部意义。如果你保留,你释放,或者否则你错了!通过 addSubview 我将分配/释放的责任交给 iOS 框架并让框架处理它。我只是想了解为什么这不能像我想象的那样工作:)
    【解决方案3】:

    因为您没有分配该按钮(加号按钮)。如果你不分配,那么你不应该释放它。移除【加释放】;

    【讨论】:

    • 但他在初始化时添加了“retain”...(实际上并不需要,在这种情况下...可以同时删除保留和释放...)
    • 嗯,到目前为止我已经读到,如果你不做分配,你会得到一个自动释放对象。如果您想使用该对象,您需要保留它,就像我一样。之后(我将它添加到应该保留的子视图中)我释放它。
    • 嗨,boney,他保留了自动释放的加号对象。并在最后释放,因此没有内存泄漏。 @Nick 有时仪器显示错误的泄漏消息。
    • @nick:好吧,您可以在使用相同方法时使用它...“plus”将是可见的,您可以调用它直到您的方法结束(并在其中).. . 你需要保留它(并在你的方法之外声明它)以防万一你需要它并想确​​保它在你需要的时候保留在内存中......
    【解决方案4】:

    仅从您发布的代码 sn-p 来看,它看起来不像泄漏。如果按照 makboney 的建议删除释放行,则还必须在开头删除加号按钮的保留。没有理由保留它,因为它是自动释放的,而且您显然不打算保留所有权超过几行代码;)

    尝试运行静态分析器(Build->Analyze)也许它会告诉你更多关于泄漏的信息。

    【讨论】:

      【解决方案5】:

      UIButton * plus = [[UIButton buttonWithType:UIButtonTypeRoundedRect] retain];中删除retain
      并删除 [plus release];

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-10-11
        • 1970-01-01
        • 1970-01-01
        • 2019-02-09
        • 1970-01-01
        • 1970-01-01
        • 2011-09-09
        • 1970-01-01
        相关资源
        最近更新 更多