与ARC的对象重新分配不一致? [英] Inconsistent object deallocation with ARC?

查看:89
本文介绍了与ARC的对象重新分配不一致?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Mac OSX 10.7的简单命令行应用程序来处理内存(取消分配)问题,该应用程序使用启用了ARC的Xcode版本4.2.1和默认的构建设置构建.我无法从我对ARC的了解中得到解释的行为,所以我希望有人可以解释这里发生的事情.

I was playing around with memory (de)allocation stuff on a simple command line app for Mac OSX 10.7 built using Xcode Version 4.2.1 with ARC enabled, and the default build settings. I can't explain the behaviour I'm getting from what I understand about ARC, so I'm hoping someone can explain what's going on here.

首先,在以下代码中,我得到了预期的行为(请注意,NLog()输出在相应语句后的注释中给出)

First off, in the following code I'm getting the behaviour I expect (please note that the NLog() output is given in the comment after the corresponding statement)

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[])
{
    NSObject *objPtr1 = [[NSObject alloc] init];
    NSObject *objPtr2 = objPtr1; 
    __weak NSObject *weakRef = objPtr1;
    NSLog(@"%@", [objPtr1 description]); // <NSObject: 0x1001107d0>
    objPtr1 = nil;
    NSLog(@"%@", [objPtr2 description]); // <NSObject: 0x1001107d0>
    objPtr2 = nil;
    NSLog(@"%@", [weakRef description]); // (null)
    return 0;
}

因此,在上面的方法中,在分配weakRef之后,NSObject实例具有两个指向它的强指针,因此保留计数为2.将objPtr1归零后,仍然有一个指向该实例的保留指针,因此它仍在内存中,并且响应描述消息.在将objPtr2设为零之后,就没有指向该对象的强指针,并且将其释放(由于弱引用已被清零,所以我假设是的).到目前为止,一切都很好.

So in the above, right after weakRef is assigned, the NSObject instance has two strong pointers to it, and therefore a retain count of 2. After zeroing objPtr1 there's still one retaining pointer to the instance, so it's still in memory and responds to the description message. After nil-ing objPtr2, there are no strong pointers to the object and it is deallocated (I'm assuming it is, since weakRef has been zeroed). So far, so good.

现在,相同的代码稍有变化:

Now, the same code with a small change:

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[])
{
    NSObject *objPtr1 = [[NSObject alloc] init];
    NSObject *objPtr2 = objPtr1; 
    __unsafe_unretained NSObject *weakRef = objPtr1; // __unsafe_unretained instead of just __weak
    NSLog(@"%@", [objPtr1 description]); // <NSObject: 0x1001107d0>

    objPtr1 = nil;
    NSLog(@"%@", [objPtr2 description]); // <NSObject: 0x1001107d0>

    objPtr2 = nil;
    NSLog(@"%@", [weakRef description]); // <NSObject: 0x1001107d0>
    //why was the object instance not deallocated and the preceding statement not crash the program?
    return 0;
}

我原以为weakRef会变成一个悬空指针,通过该消息发送一条消息,该消息将导致程序在第三条NSLog()语句中崩溃,但是看来该对象实例仍然有效.

I was expecting weakRef to become a dangling pointer sending a message through which would cause the program to crash in the third NSLog() statement, but it seems the object instance is still alive and well.

我觉得很奇怪的另一件事:

Another thing I find weird:

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[])
{

    NSObject *objPtr1 = [[NSObject alloc] init];
    NSObject *objPtr2 = objPtr1; 
    __weak NSObject *weakRef = objPtr1; // __weak again
    NSLog(@"%@", [weakRef description]); // <NSObject: 0x1001107d0>

    objPtr1 = nil;
    NSLog(@"%@", [weakRef description]); // <NSObject: 0x1001107d0>

    objPtr2 = nil;
    NSLog(@"%@", [weakRef description]); // <NSObject: 0x1001107d0>

    return 0;

}

最后一个代码类似于第一个代码(使用置零的__weak指针);唯一的不同是,在三个NSLog()调用中的每一个中,描述消息都是通过weakRef发送给对象的.但是这次,即使删除了两个强引用,该对象也不会被释放(因为它仍然通过weakRef响应消息).

This last code is like the first one (using the zeroed __weak pointer); the only difference is that the description message was sent to the object through weakRef in each of the three NSLog() calls. But this time round the object isn't deallocated even after the two strong references have been removed (since it's still responding to messages through weakRef).

那么这是怎么回事?

推荐答案

如果您反汇编A.R.C.生成的代码,则对弱变量的每次访问都将包装在对该函数的调用中:

If you disassemble A.R.C.-produced code, every access to a weak variable is wrapped in a call to this function:

id objc_loadWeak(id *location)
{
    return objc_autorelease(objc_loadWeakRetained(location));
}

这将检查对象是否已经被释放,如果没有,则保留并自动释放该对象,以防过早释放.

This checks if the object has already been dealloced, and if not, retains and autoreleases it, for extra safety against premature deallocs.

因此,在您的第三个示例中,对弱引用方法的早期调用导致其保留计数增加,因此,对指针进行调零不会导致其被释放.

Therefore in your third example, the early calls to method on weakRef are causing its retain count to be increased, so nilling your pointers doesn't cause it to be dealloced.

这篇关于与ARC的对象重新分配不一致?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆