views:

180

answers:

2

Hi

I have this simple code

@interface chatApp4Message : NSObject {
NSString* line;
}
@property (nonatomic, retain) NSString* line;
@end

@implementation chatApp4Message
@synthesize line;
@end

As you can see, I don't release the line property. However, when running this following simple code under the xCode leaks tool, I get no indication of memory leaks

for (int i=1; i< 100; i++){
    chatApp4Message* msg = [[chatApp4Message alloc] init];
    msg.line = @"aaaaaa";
    [msg release]
}

Any reply will be appreciated

+2  A: 

Actually there's no memory leaks in your code. @"aaaaaa" is a string literal object and is created at compile time and it persists all the time your application runs. However change your code to really create string object and you'll get memory leak:

for (int i=1; i< 100; i++){
    chatApp4Message* msg = [[chatApp4Message alloc] init];
    msg.line = [NSString stringWithFormat:@"%d", i]; // It leaks!
    [msg release]
}

P.S. May be this discussion on string literals will be useful...

Vladimir
Really? I thought the `@synthesize`'d `@property(retain)` would release it's ivar and then retain the new one. No leaks until dealloc, and only if `[line release]` is missing.. and of course `line=nil` during initialization to keep things safe and tidy
ohhorob
That's all true and to handle memory correctly you need to release line ivar in dealloc method. I just tried to explain (may be poorly - sorry I'm not a native speaker) why in **that particular** example there's no memory leak. String literals does not behave like ordinary dynamically created obj-c objects(see link posted) - for example you can try to release/retain string literal and check that they don't affect literal's retain count.
Vladimir
dealloc method will get called right after [msg release] even if you don't override it in chatApp4Message class. And ivars (at least obj-c objects) are initialized with nil by default anyway - you don't need to set them as nil in init method.
Vladimir
I don't dispute the literal string memory management, but you have "// It leaks!" on a line where an autoreleased string is assigned to a retained property. It doesn't leak!! If it was `msg.line = [[NSString alloc] initWithFormat:@"%d",i];` then I would agree.
ohhorob
+2  A: 
  1. Your code is technically leaking for the reasons you think, but Instruments is measuring reality, not theory. If you were to run the static analyzer on your code (Build & Analyze), it should detect the leak.

  2. String literals -- @"...." -- are actual compiled static NSString instances. At runtime, [@"foo" class] would indicate that the string is an instance of NSCFConstantString (IIRC -- some constant string class anyway) that does nothing on retain, release, or autorelease, because it isn't actually an allocated instance.

  3. If you want to play with Leaks analysis, do so with mutable strings or with instances of some class you create.

I often use a function like the following to generate mutable self-identifying string instances to futz with leaks or object graph analysis:

 NSString *testString(NSString *prefix) {
     NSMutableString *s = [NSMutableString stringWithString: prefix];
     [s appendFormat: @" (%p)", s];
     return s;
 }
bbum