views:

341

answers:

2

hi,

I am using a simple function to display messages to user through a label. The function is as follows:

-(void) showMessage:(NSString*) message {

Message.text = message; [message release]; }

There is no memory leak if I call this function from the main thread. But if I call this function from a separate thread, the instruments monitor shows a 16 byte memory leaks as soon as the function is called. The leak is not seen if I comment out the function call. Does anyone know why ? I am using iPhone SDK 3.0. The instruments monitor does not point to any of my functions to indicate the leak. It only shows a function or two from UILabel.

+2  A: 

Looking at your code there, it seems you've got memory management wrong somewhere - you should never release an object you receive as a method parameter. Consider the following:

-(void)doSomething {

    NSString *aStr = [[NSString alloc] init];

    [self showMessage:aStr];

    NSString *anotherStr = [aStr stringByAppendingString:@"Hi"];
    // ^^ This call will crash as aStr has been released and is invalid.
}

-(void) showMessage:(NSString*) message {
    Message.text = message; 
    [message release];
}

... Using your method in the above example will cause a crash, because the showMessage: method releases the passed string.

I know this doesn't directly answer your question, but get memory management right and your problems may well go away. I suggest you read Apple's Memory Management Programming Guide for Cocoa.

Edit: Also, UIKit isn't thread-safe - you should never call a message to a UIKit object from anything but the main thread. See performSelectorOnMainThread:withObject: for calling a message on the main thread from another thread.

iKenndac
iKenndac got it right. Remove the [message release] from your code.
Jordan
In my project, I am using a lot of messgaes to be thrown to the user. So I am keeping all of them in a 'constants' file like: NSString * const testString = @"Hello";Then I am passing this testString to the showMessage function. It doesn't matter if I do a [message release] or not. I commented that line and the leak still exists.I tried [self performSelectorOnMainThread:@selector(showMessage) withObject:yourTurn waitUntilDone: NO]; but it doesn't display the message, and crashes on the next user interaction.I repeat, the function doesn't leak when called from main thread.
tuttu47
A: 

It is hard to make out from this piece of code. Also, instruments is not a perfect mechanism, certainly not for finding (and solving) leaks of this size..

It is probably not even a leak, but that depends on how you initialize and release the message string before and after the function call.

If you initialize it like this;

NSString *message = [[NSString alloc] initWithString:@"hello"];

Message will receive a retain count of +1, and you have to release it after you've passed it as a parameter to your function.. Inside the function it will be retained again by the label. If you initialized it with an autorelease message, then it's a whole different story.

Also, when you are working with NSThread, use the NSAutoreleasePool in your methods.

I'd also suggest running XCode's static analyzer, which may help you find improper memory management.

MiRAGe
In my project, I am using a lot of messgaes to be thrown to the user. So I am keeping all of them in a 'constants' file like: NSString * const testString = @"Hello"; Then I am passing this testString to the showMessage function. It doesn't matter if I do a [message release] or not. I commented that line and the leak still exists.I tried using the clang Static Analyzer. It gives me no leaks. Is this small leak OK ? I mean, can I just ignore it ?
tuttu47
If it is a constant, you should skip the [message release] part. If Message is a UILabel it will retain (and release) the message when it feels appropriate. The leaks instrument isn't the best in the world, I'd suggest to assume the static analyzer results are true.
MiRAGe