Chrysotribax Chrysotribax - 6 months ago 14
iOS Question

NSString : leak when assigning value to a property

Assuming we don't use ARC.
Suppose we have a very simple class in which we declare 2 NSString properties, like this :

@interface Foo : UIView {}
-(id)initWithArguments:(NSString*)mess title:(NSString*)tit;

@property(nonatomic, retain) NSString *message;
@property(nonatomic, retain) NSString *title;
@end


and in implementation :

@implementation Foo
@synthesize message, title;

-(id)initWithArguments:(NSString*)mess title:(NSString*)tit{
if((self = [super init])){
message = mess; // (1)
self.title = tit; // (2)
(...)
}
return self;
}

-(void)dealloc{
message = nil;
title = nil;
[super dealloc];
}
@end


Now if I call a method from another class, in which I create 2 NSString and an instance of Foo , like this :

-(void)someMethod{
NSString *string1 = [NSString stringWithFormat:@"some text with %d things", 5];
NSString *string2 = [NSString stringWithFormat:@"other text with %d things", 5];

Foo *foo = [[Foo alloc] initWithArguments:string1 title:string2];
}


The whole code works fine and doesn't crash, but, if I profile it with instruments,


  • it doesn't cause a leak when calling (1)("message = mess;")

  • it cause a leak when calling (2)("self.title = tit;")



It's very confusing, because stringWithFormat is an autoreleased object, isn't it ?
So, how an autoreleased object can cause a leak when assigning to a property ???

I read somewhere that it's almost always better to use the "self.text = value;" form instead of the "text = value;" form, because the second one may cause a leak.

Actually, in this code it's the contrary.

And... If I use a constant NSString like @"some text", instead of the values returned by [NSString stringWithFormat], there is no leak, of course.

Any idea ?

Answer

You have forgotten to invoke the (compiler-generated) setter methods in a few cases:

self.message = mess;    // in init method

self.message = nil;     // in dealloc method
self.title = nil;       // ditto

It's crucial that you use the setter/getter methods in non-ARC code.