目标C内存管理困境

时间:2010-07-09 13:52:18

标签: objective-c memory-management nsstring nsarray nsobject

我知道这已被讨论过,但我只是没有得到一些内存管理。我知道retain会使对象保持活动状态,copy会为对象提供一个单独的对象副本。

我不知道的是当涉及到ivars&属性,保留为属性意味着setter释放旧值&保留新的:

property = newValue;
// retain
if (property != newValue)
{
   [property release];
    property = [newValue retain];
}

但是我看过他们将静态字符串分配给retain属性的示例,例如。

self.stringProperty = @"something";
(some other code)
self.stringProperty = @"somethingElse";

第二次调用set string应该调用静态字符串上的release是不允许的,为什么程序不会崩溃?

此外,如果使用retain属性声明一个对象&然后用init分配一些东西,例如

@property(retain)someArray;

someArray = [[NSArray alloc] initWithArray:arbArray];

这是否意味着someArray现在的保留计数为2,但如果它是用

创建的
someArray = [NSArray arrayWithArray:arbArray];

保留计数仅为1,因为第二个是工厂方法?

3 个答案:

答案 0 :(得分:3)

  

第二次调用set string应该调用静态字符串上的release是不允许的,为什么程序不会崩溃?

您可以将release传递给常量字符串,它不会做任何有意义的事情,因此这些代码行是有效的。

  

这是否意味着someArray现在的保留计数为2,但如果它是用...创建的,则保留计数仅为1,因为第二个是工厂方法?

嗯,首先,

someArray = [[NSArray alloc] initWithArray:arbArray];

不使用@property创建的方法,只是直接访问ivar。要使用属性方法,您必须使用self.someArray = ...;

但是,是的,

[[NSArray alloc] initWithArray:arbArray]

返回有效保留计数为1的对象,

[NSArray arrayWithArray:arbArray]

返回有效保留计数为0的对象,因此,如果 通过@property创建的“保留”设置器传递它们,则ivar的有效保留计数为分别为2和1。

答案 1 :(得分:0)

这是一个问题,但无论如何......

静态字符串在很多方面都是特殊情况,其中一种方法是,您可以retainrelease将它们放在心中,而不会产生任何影响。

另外,NString属性通常具有copy而不是retain语义,如果重要的话,无论如何都会消除该问题。但事实并非如此。

在第二种情况下,直接从retain(或alloc或其他所有权授予电话)分配copy属性是不好的做法,除非您主动添加相应的release之后,或autorelease期间,例如:

self.someArray = [[[NSArray alloc] initWithArray:arbArray] autorelease];

但是在这种特殊情况下,没有理由不使用类方法。

答案 2 :(得分:0)

  

第二次调用set string应该调用静态字符串上的release是不允许的,为什么程序不会崩溃?

它不是一个静态字符串,它是一个常量字符串。但是,这与问题无关,但实际上您可以发送-retain到从NSObject 派生的任何Objective-C对象,除了 NSAutoreleasePool。如果你看看一个常量NSString的retainCount(有点顽皮,但是因为我们正在讨论实现,OK),例如。

NSLog(@"retain count = %u", [@"foo" retainCount]);

你很可能会发现它被设置为一个非常大的数字(实际上是UINT_MAX)。这是运行时忽略释放和保留调用的信号。

顺便说一下,忘记释放对象不会立即导致程序崩溃。实际上,如果你有大量的RAM,在操作系统开始交换之前你可能不会注意到。

  

这是否意味着someArray现在的保留计数为2,但如果它是用

创建的

不,因为您没有使用该属性来分配新数组,所以您直接进入了ivar:

self.someArray = [[NSArray alloc] initWithArray:arbArray];

会泄漏。

self.someArray = [NSArray arrayWithArray:arbArray];

没关系。