【问题标题】:Objective-C - autoreleasepool (ARC - Automatic reference Counting)Objective-C - autoreleasepool (ARC - 自动引用计数)
【发布时间】:2012-01-11 23:39:18
【问题描述】:

我对自动引用计数 (ARC) 中的 autoreleasepool 存有疑问

在我的示例(粘贴在下面)中,我有一个 autoreleasepool,并且在 autoreleasepool 块中没有语句。在 autoreleasepool 块之后有一个 autoreleased 实例 (a3)。

预期行为:

我预计以下语句会导致内存泄漏,因为它没有封装在自动释放池中。

A* a3 = b1.xa1;

实际行为:

实际行为是在运行时没有抛出内存泄漏错误

注意:

如果在a3初始化后移动了autoreleasepool,那么在运行时会抛出内存泄漏错误

我的理解:

只有在 autoreleasepool 中的语句才会具有 autorelease pool 的效果,但根据我的示例,情况似乎并非如此。

问题:

  1. 发生这种情况的原因是什么?
  2. 是否有任何意义 用自动释放池块封闭语句?还是很好 足以在之前有一个空的 autoreleasepool 块 自动发布的实例?如果是,为什么?

我的问题总结

问题更多是关于在 autoreleasepool 中包含语句似乎与在 autoreleasepool 之后放置语句具有相同的效果,即使它在 autoreleasepool 之外

代码:

#import<Foundation/Foundation.h>

@interface A : NSObject
- (void) dealloc;
@end

@implementation A
- (void) dealloc { printf("instance of A deallocated = %p\n", self); };
@end

@interface B : NSObject
@property (weak) A* xa1;
- (void) dealloc;
@end

@implementation B
@synthesize xa1;
- (void) dealloc { printf("instance of B deallocated = %p\n", self); };
@end

int main()
{
    system("clear");

    B* b1 = [[B alloc] init];
    A* a1 = [[A alloc] init];
    A* a2 = [[A alloc] init];

    b1.xa1 = a1; 

    @autoreleasepool
    {}  

    A* a3 = b1.xa1;                     //I expected this to throw a memory leak error, but it doesn't
                                        //Note - b1.xa1 returns an autoreleased instance

    printf("--- end of main\n");

    return(0);
}

【问题讨论】:

  • 什么是“内存泄漏错误”?您看到的文字是什么,在什么背景下?
  • 下面贴出内存泄漏错误(当autoreleasepool a3初始化移到autoreleasepool之前):objc[2668]: Object 0x105313b90 of class A autoreleased with no pool in place - just leaking - break on objc_autoreleaseNoPool() to debug

标签: objective-c automatic-ref-counting autorelease


【解决方案1】:
  1. 发生这种情况的原因是什么?

虽然我认为A* a3 = b1.xa1; 行在技术上是“错误的”,但 ARC 足够聪明,可以在不实际使用自动释放池的情况下正确处理返回的对象。这是 ARC 的性能优化(自动释放池的使用不是免费的)。基本上,ARC 正在注入 [a1 relea 来自苹果的Transitioning to ARC Release Notes

编译器有效地消除了许多无关的保留/释放 调用并投入了大量精力来加速 Objective-C 运行时一般。特别是,常见的“返回 保留/自动释放对象”模式要快得多,而且不会 实际上是把对象放入自动释放池中,当调用者 方法是ARC代码。


  1. 用自动释放池封闭语句有什么意义吗?还是有一个空的就足够了 自动释放实例之前的自动释放池块?如果是,为什么?

是的。虽然这种特殊情况恰好表明并非如此,但一般来说,自动释放池是有意义的。本文档中关于自动释放池的所有内容仍然有效:http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html

【讨论】:

  • 感谢 Josh 的回复,但 A* a3 = b1.xa1 会自动释放 n 个实例,弱属性的 getter 会自动释放实例。如果在运行时注释掉 autoreleasepool 会导致抛出内存泄漏错误
  • 嗯...好吧,如果是这样的话,我将删除我的编辑并回退到我原来的答案:) 我曾假设弱属性只是像经典的分配属性一样返回它们的 ivar,但是看来我错了。介意我指向一些明确声明这一点的文件吗?到目前为止,我发现的只是这个线程:comments.gmane.org/gmane.comp.compilers.clang.devel/15959
  • 编辑的评论我没有找到明确支持我理解的文档。但是,我根据一组示例发现以下情况是正确的:除assignunsafe_unretained 之外的所有存储/所有权属性的getter 将保留并自动释放实例。总之strong/weak/copy/retain都会保留并自动释放
  • 我确实理解 autoreleasepool 的重要性,但我不明白为什么实际行为不符合我的预期行为(参见上面的原始帖子)。问题更多是关于在 autoreleasepool 中包含语句似乎与在 autoreleasepool 之后放置语句具有相同的效果,即使它在 autoreleasepool 之外
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-05-23
  • 1970-01-01
  • 1970-01-01
  • 2012-03-21
  • 2012-03-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多