2

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

我不明白的是,当涉及到 ivars 和属性时,将其保留为属性意味着 setter 释放旧值并保留新值:

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

但我见过他们将静态字符串分配给保留属性 ivars 的示例,例如

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

设置字符串的第二次调用应该在不允许的静态字符串上调用释放,为什么程序不会崩溃?

另外,如果一个对象是用retain属性声明的,然后用init分配一些东西,例如

@property(retain)someArray;

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

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

someArray = [NSArray arrayWithArray:arbArray];

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

4

3 回答 3

3

设置字符串的第二次调用应该在不允许的静态字符串上调用释放,为什么程序不会崩溃?

您可以传递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。

于 2010-07-09T14:01:57.570 回答
0

设置字符串的第二次调用应该在不允许的静态字符串上调用释放,为什么程序不会崩溃?

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

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

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

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

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

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

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

将是泄漏。

self.someArray = [NSArray arrayWithArray:arbArray];

会好的。

于 2010-07-09T15:27:45.807 回答
0

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

retain静态字符串在很多方面都是特殊情况,其中之一是您可以release随心所欲地使用它们而不会产生任何影响。

顺便说一句,NString属性通常具有copy而不是retain语义,如果重要的话,无论如何都会避免这个问题。但事实并非如此。

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

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

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

于 2010-07-09T14:02:46.337 回答