为什么破坏保留周期不会像这样陷入无限循环?

时间:2014-04-16 06:08:58

标签: ios objective-c memory-management

以下是我验证问题的代码。

0。模拟保留周期

我创建了两个类,A& B:

@interface A : NSObject

@property (strong, nonatomic) B *b;

@end

@implementation A

- (void)dealloc
{
    [_b release];
    [super dealloc];
}

@end

//

@interface B : NSObject

@property (nonatomic, strong) A *a;

@end

@implementation B

- (void)dealloc
{
    [_a release];
    [super dealloc];
}

@end

//在StrongViewController中,有tempA和tempB,它们都是proprety:

@interface StrongViewController ()

@property (nonatomic, assign) A *tempA;
@property (nonatomic, assign) B *tempB;

@end

//在viewDidLoad中,我创建了一个保留周期,一个& b互相保留:

A *a = [[[A alloc] init] autorelease];
B *b = [[[B alloc] init] autorelease];

a.b = b;
b.a = a;

self.tempA = a;
self.tempB = b;

//然后在viewWillDisappear中,我尝试打破保留周期:

[super viewWillDisappear:animated];
self.tempA.b = nil; // Key line

//现在,逐步进入循环。

1。使用默认设置器来中断保留周期

我在A的dealloc&中设置了两个断点。 B的dealloc:

enter image description here enter image description here

//现在执行了关键行self.tempA.b = nil;

enter image description here

// B已dealloc被调用,因为release消息已发送到A setB中的b:

enter image description here

enter image description here

//在B的dealloc中,release消息被发送到a,因此A的dealloc被调用:

enter image description here

enter image description here

//现在,_b是nil因为我们使用默认的setB:,所以可以通过。

2。使用自定义setter来中断retain-cycle

//但是如果使用如下所示的自定义setB:会怎么样:

enter image description here

//执行关键线self.tempA.b = nil;后,它会遇到自定义setB:

enter image description here

//现在release被发送到b,所以它转到了B的dealloc

//请注意,在B的dealloc中,[self retainCount]仍为1,而不是0,为什么?

enter image description here enter image description here

//在B的dealloc中,release被发送到_a,因此它将依次转到A的dealloc,并在那里release将被发送到_b:

enter image description here enter image description here

//差异很大,在A的dealloc中,_b不是nil,_b的retainCount是1。

//据我所知,如果_b现在收到release消息,那么它会调用dealloc,因为它的retainCount目前为1。

//但是,出于我的想象,它不会递归地进入B的dealloc,而只是跳到下一行,让retainCount具有较大的值{{1} }:

enter image description here

3。我的问题

//我的问题是上述问题,为什么当_b收到2147483648消息时,它会跳过,而不是踩到release,而dealloc仍然 1

// retainCount retainCount是如何出来的?

//深入了解NSObject在收到“发布”消息时的工作原理,任何人都知道源代码?即使在A 2147483648中, a 的retainCount`仍为1, b 也是如此。

3 个答案:

答案 0 :(得分:3)

当您释放保留计数为1的对象时,会发生以下情况:

该对象标记为“死”。

调用dealloc方法。

对象的内存返回给操作系统。

当对象标记为死时,

保留和释放无效。在调用dealloc之前,运行时甚至不打算将retain count设置为零。当您的第二个dealloc方法被调用并尝试释放已经死亡的对象时,即使retainCount返回1,也没有任何反应。对于同一个对象,dealloc永远不会被调用两次。

答案 1 :(得分:1)

http://www.opensource.apple.com/source/objc4/objc4-532/runtime/NSObject.mm值得一试。

我认为问题与hasCustomRR()有关,但我发现代码很难跟随,所以可能是错误的。

答案 2 :(得分:-1)

不要在对象之间保持循环引用! 但是需要一些时间来使用这些引用来完成我们的任务。 所以我建议如果你有一个对象依赖于其他,那么你可以使用参考WEAK.It将确保打破引用的循环循环。您可以参考http://www.cocoawithlove.com/2009/07/rules-to-avoid-retain-cycles.html教程获取更多解释。