我发现如果我在Class方法中分配一个新对象并将其返回给main(),那么当我不再需要该对象时,它似乎会导致内存泄漏。
例如,这是一个简单的Class,它包含一个返回其自身实例的Class方法:
@interface Stinker : NSObject
{
int a;
}
+(instancetype) makeAStink;
-(void) showThem;
-(void) setEm: (int) z;
@end
@implementation Stinker
-(void) showThem
{
NSLog(@"%d",a);
}
-(void) setEm: (int) z
{
a = z;
}
-(void) dealloc
{
NSLog(@"Arrrgggggh!");
}
+(instancetype) makeAStink
{
id temp = [[self alloc] init];
return temp;
}
@end
现在,如果我直接从main()创建一个实例:
Stinker *aStink =[[self alloc] init];
然后将aStink设置为nil:
aStink = nil;
调用重写的dealloc方法和Argggggh!消息已记录。这很好并且符合预期。
但是如果我使用我编写的Class方法来创建一个实例:
Stinker *aNewStink = [Stinker makeAStink];
行为不同。
现在,如果我将aNewStink设置为nil,它将不再指向对象但对象未被销毁。不调用dealloc并且不记录Arggggh消息。
似乎它仍然拥有某个所有者。
当然,当main()终止时,对象被销毁并最终调用dealloc。 但这似乎表明,在程序终止之前,未使用和不受欢迎的对象仍然在堆上闲置。
这不是内存泄漏吗? 我应该避免使用Class方法来分配新实例吗?
答案 0 :(得分:0)
这是您的示例的MRC(没有ARC)代码
+(instancetype) makeAStink
{
id temp = [[self alloc] init];
return [temp autorelease];
}
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
id obj = [Stinker makeAStink]; // obj is autoreleased object
id obj2 = [[Stinker alloc] init]; // obj2 is not autoreleased
[obj2 release]; // so you need to release it
[pool release]; // now obj is released and deallocated
所以obj
有一个额外的保留计数,将在下一个runloop中释放(和解除分配),而obj2
将在调用release
时立即释放
这不是内存泄漏,这是通常的行为,并且(通常)不会以明显的方式影响程序性能
答案 1 :(得分:0)
使用ARC时,以下代码
+(instancetype) makeAStink
{
id temp = [[self alloc] init];
return temp;
}
与Non-ARC相同:
+(instancetype) makeAStink
{
id temp = [[self alloc] init];
return [temp autorelease];
}
感谢自动释放,aNewStink = nil
将使newNewStink在下一个runloop中发布。
所以,如果你这样做:
@autoreleasepool {
Stinker *aNewStink = [Stinker makeAStink];
aNewStink = nil;
}
立即调用Dealloc方法。