Copied blocks and CLANG leak warnings - ios5

I have a method which takes a block:
- (void)methodWithBlock:(blockType)block
The method starts out by copying block, because it does asynchronous things before using it, and it would be discarded otherwise. It then calls the method within another block, and then releases it, within that block. Summarily:
- (void)methodWithBlock:(blockType)block
{
block = [block copy];
[something asyncStuffWithFinishedBlock:^{
// ..
block();
[block release];
}];
}
CLANG complains about memory leaks for "block". If I remove the copy and release statements the block will be gone by the time it's called -- at least earlier crashes indicates that this is the case.
Is this the wrong way to do things? If so, how should I do the above -- i.e. a block callback from within a block statement in a method? I can't store block as an instance variable, as the method could be called repeatedly with different arguments while the asynchronous part is happening.

First, the -copy and -release should be unnecessary. The -asyncStuffWithFinishedBlock: method must copy the block that's passed to it. When a block is copied and it references other block objects, it copies those block objects, too. You need to figure out the real nature of the crash you were seeing.
Second, you are releasing the wrong thing. [block copy] does not modify the block (the receiver of the -copy message) somehow turning it into a copy. It returns a copy of that block. It is this returned copy that you want to reference both in the invocation statement (block();) and when releasing.
So, you could do:
block = [block copy];
[something asyncStuffWithFinishedBlock:^{
// ..
block();
[block release];
}];
Note the reassignment of the local block variable to point to the copy.
Think of it this way: would you ever copy a string the way you attempted to copy that block? Would you do:
[someString copy];
// ... use someString ...
[someString release];

I don't think you should do the release inside the block like that. You are assuming that the block gets called exactly once. But just from the code, we don't know that. It could be that the method does not execute the block at all, in which case you won't be releasing, so leaking. It could also be the case that the method executes the block more than once, in which case you would be over-releasing.
If you really want to copy it, you need to release it outside the block like this (the scope that retains something should be responsible for releasing it):
- (void)methodWithBlock:(blockType)block
{
block = [block copy];
[something asyncStuffWithFinishedBlock:^{
// ..
block();
}];
[block release];
}
(It's irrelevant what asyncStuffWithFinishedBlock might to with its argument; according to the memory management rules, if it needs to keep it around for longer, it will need to retain or copy it (for blocks it needs to copy it).)
However, as Ken Thomas pointed out, it shouldn't be necessary for you to copy it in this method since you're not storing the block anywhere. asyncStuffWithFinishedBlock should copy its argument block if it needs to run it asynchronously; and any blocks captured by that block should be copied when it is copied.

Related

autoreleasepool inside a method on ARC

I am wondering if there's any benefit of using #autoreleasepool on an ARC code inside a method.
I mean this. Suppose I have a memory intensive method that is called several times in sequence. Something like
// this is my code
for (id oneObject in objects {
[self letsUseMemory];
}
and then
- (void) letsUseMemory {
// heavy use of memory here
}
and I do this
- (void) letsUseMemory {
#autoreleasepool {
// heavy use of memory here
}
}
Is there any benefit? I mean, the method variables will be deallocated anyway when the method finishes, so adding an autoreleasepool there, in theory, will do any benefit, right?
Or will autoreleasepool inside that method speed the deallocation?
thanks.
Is there any benefit? I mean, the method variables will be deallocated anyway when the method finishes, so adding an autoreleasepool there, in theory, will do any benefit, right?
It depends. Any autoreleased temporary objects will not be deallocated until the pool drains, regardless of whether you're using ARC. I.e.:
NSString* foo = [NSString stringWithFormat:#"Bar: %#", baz];
Without an enclosing #autoreleasepool, that object instance may hang around until you return to the run-loop. If that line of code exists within a loop, you may be accumulating a large number of these temporary objects.
The general rule of thumb is that if you have a potentially large loop that may create autoreleased objects, wrap the inside of the loop in with an #autoreleasepool.
It's less common and perhaps somewhat meaningless to wrap a single method in an #autoreleasepool because it would usually only have meaningful effect if the method was called many times in a loop. Putting the #autorelease pool in the loop makes the intent more clear.
There are a number of "it depends" things going on there, I believe.
Starting with the obvious, if there are no autoreleased objects, it doesn't matter. If your code goes right back to the run loop after your enumeration finishes, it doesn't matter.
That leaves the case where the method containing the enumeration is used to do a bunch of initialization and then continues on with more processing. For that one, you could benefit by getting rid of temporary objects that were marked for later release.

iOS correct way (memory management) for a method to return a value

If I have a class named Foo and I have this function + getIds that should return ids. Would the correct signature of + getIds look like this:
+ (NSArray *)getIds {
NSMutableArray *ids = [[[NSMutableArray alloc] init] autorelease];
return ids;
}
What I'm wondering is that if I should use autorelease on *ids? There is no other way I assume? I can't do [ids release] after the return statement right?
You can send autorelease message along with alloc, init messages. You can also do, return [ids autorelease]; Note: You should not do both at the same time ;-)
You can not return [id release], because release method itself returns nothing.
The typically-correct memory management for returned objects is to have the called method set it as an autoreleased object, except when the method name contains "copy", "new" or "alloc". In those cases (copy/new/alloc), the returned object is retained, and the caller owns it (i.e. the caller is responsible for making sure they are released).
The code you wrote in the question will do the correct thing - it will return an autoreleased object.
When the caller gets the NSArray back, they can use the object as much as they like, and if they don't need the object in future calls, then they don't need to do any extra memory management. At the end of the run loop, the NSArray will be released, which is the desired behavior. If the caller does need the object to live longer, then they have to call retain on it (or something equivalent to that, such as calling something else that calls retain on it), and then they take the responsibility to call release on it later.
Useful stuff:
Apple's iOS memory management guide
My personal memory management guidelines (shorter, more biased)
Understanding run loops
Also, this will all go away when ARC (automatic reference counting, in iOS 5) becomes the norm.
You are already autoreleasing the array, so calling autorelease a second time would be an error that might result in a crash. The fact that you can't do a release after the return (you've left the function by then) is one of the reasons autorelease exists.
About whether the method should return an autoreleased as opposed to a retained object: Only methods that start with alloc or new or contain copy (as in mutableCopy) shall return retained objects. All other method shall return autoreleased objects.

About using convenient method and the time of their autorelease

This maybe too basic but I couldn't find an exact answer. I'll be happy to delete/close this post if anyone point me to similar posts.
I want to call method "getString" to return a formatted string and set to my label like this:
-(NSString*) getString {
NSString *result = [NSString stringWithFormat:#"blah blah %#", someOtherString];
return result;
}
-(void) viewDidLoad {
someLabel.text = [self getString];
}
This code worked for me, but I am concerned that result is allocated by a convenient method thus may be auto-released before it got retained by the label. Is it true? If so, when exactly would an object from convenient method get released?
Second question, if in case I have to use [NSString alloc] to create my own string object. Where and how should I release it?
Thanks in advance
Leo
It isn't true that the object will be autoreleased before you retain it. The details of when the pool gets drained are unimportant to answer this question, except that it can't happen during your code unless you call drain or release on the pool. If your function calls another function, except in some specific edge cases both the function you call and the function you called from need to exit before that thread can do anything else. The autorelease pool is thread-specific.
To answer your second question, if you alloc an object you should release it when you've finished using it. Simple as that. That includes when you pass it to other code that needs it, because it should be up to that other code to claim ownership if it needs to.
This code worked for me, but I am concerned that result is allocated by a convenient method thus may be auto-released before it got retained by the label.
Yes, it will be autoreleased because it is returned by a method whose name does not contain new, alloc or copy. No, this won't happen before the calling method viewDidLoad returns.
In fact, the autorelease-pool, to which it's added will probably be the one set-up and teared-down by the runloop, so nothing is going to happen to it until the end of the current iteration through the runloop.

Trying to understand blocks on iOS

I am trying to understand how to use blocks on iOS. I have read Apple's docs but, as usual, they are vague and incomplete and several essential bits of information are not mentioned. I have also googled around without success. This is what I am trying to do as an exercise to understand that.
I have created a block to read a string and compare the string to the previous read. If the strings are not the same, return YES, if they are the same, return NO.
This is how I did:
I declared this on .h
BOOL (^differentStrings)(void);
I declared this on .m, inside viewDidLoad in a viewController
__block NSString * previousString;
__block NSString * currentString;
differentStrings = ^(void){
currentString = [self getString];
NSLog(#"%#", currentString); // not printing anything on console
if (![currentString isEqualToString:previousString]) {
previousString = currentString;
return YES;
} else {
return NO;
}
};
This is how I use: I have a thread that does this:
if (differentStrings)
NSLog (#"strings are different);
These are the problems I have:
the block always return YES (strings are different)
I am not comfortable declaring this inside videDidLoad. How should I declare this, so I can use it globally as a method? Should I put this like I would with a method?
I am calling a method "getString" inside the block. Is it OK?
I find strange to declare the block variables on .m. As I see, I should declare the block variables on .h and then just use them on .m. I have tried to do that, but received an error.
I have setup a debugging point on the first line of the block but it is not stopping there;
NSlog line inside the block do not prints anything. Isn't the block being called?
Can you guys help me with this?
You're misunderstanding how blocks work. (Okay, so that's kinda obvious.) In the same way that previousString is a variable pointing to an NSString, differentStrings is a variable pointing to a block. Not the result of running the block, but rather, the block itself. That is, after you do this:
__block NSString * previousString;
__block NSString * currentString;
differentStrings = ^(void){
currentString = [self getString];
NSLog(#"%#", currentString); // not printing anything on console
if (![currentString isEqualToString:previousString]) {
previousString = currentString;
return YES;
} else {
return NO;
}
};
differentStrings is a variable pointing to the block.Thus, when you do this:
if (differentStrings)
…you're simply checking whether differentStrings contains something other than 0 or NULL. Since it contains a block, it is not empty, so it evaluates to true.
Remember: differentStrings is a block variable, not a BOOL variable. It contains a block (a function, if you will), which when called will return a bool. Thus, in order to actually run the block, you need to call it. Like this:
differentStrings();
or, in your case:
if (differentStrings()) {
NSLog (#"strings are different");
}
Edit: As pointed out in the comments, since differentStrings is an instance variable, you need to copy it, just like you'd call retain on any other object assigned to an instance variable. (For technical reasons I won't go into now, you should always use copy with blocks instead of retain.) Likewise, you'll need to call release on it at some point later, perhaps in your dealloc method.
I don't believe you're actually executing the block. I think your code should be
if (differentStrings())
{
NSLog (#"strings are different);
}
Treat a block like a function. I think you were just checking to see whether the block had been defined, not executing it.
Also, if you don't need to access an NSString outside of the block, you could get rid of the __block qualifier and move the currentString declaration inside of the block.
If you need another resource on blocks, I cover them in the fall session of my advanced iOS development course on iTunes U. I describe block syntax in the Understanding Cocoa session, and their use in Grand Central Dispatch within the multithreading session. The course notes also have links to some sample applications that use blocks in different ways.
I also can't recommend highly enough that you watch the WWDC 2010 video sessions 206 - Introducing Blocks and Grand Central Dispatch on iPhone and 211 - Simplifying iPhone App Development with Grand Central Dispatch.

Why should a self-implemented getter retain and autorelease the returned object?

Example:
- (NSString*) title {
return [[title retain] autorelease];
}
The setter actually retained it already, right? and actually nobody should bypass the Setter... so I wonder why the getter not just returns the object? It's actually retained already. Or would this just be needed in case that in the mean time another objects gets passed to the setter?
From here http://www.macosxguru.net/article.php?story=20030713184140267
- (id)getMyInstance
{
return myInstanceVar ;
}
or
- (id)getMyInstance
{
return [[myInstanceVar retain] autorelease] ;
}
What's the difference ?
The second one allows the caller to get an instance variable of a container object, dispose of the container and continue to play with the instance variable until the next release of the current autoreleased pool, without being hurt by the release of the instance variable indirectly generated by the release of its container:
aLocalVar = [aContainer getAnInstanceVar] ;
[aContainer release];
doSomething(aLocalVar);
If the "get" is implemented in the first form, you should write:
aLocalVar = [[aContainer getAnInstanceVar] retain];
[aContainer release];
doSomething(aLocalVar);
[aLovalVar release];
The first form is a little bit more efficent in term of code execution speed.
However, if you are writing frameworks to be used by others, maybe the second version should be recommanded: it makes life a little bit easier to people using your framework: they don't have to think too much about what they are doing…;)
If you choose the first style version, state it clearly in your documentation… Whatever way you will be choosing, remember that changing from version 1 to version 2 is save for client code, when going back from version 2 to version 1 will break existing client code…
It's not just for cases where someone releases the container, since in that case it's more obvious that they should retain the object themselves. Consider this code:
NSString* newValue = #"new";
NSString* oldValue = [foo someStringValue];
[foo setSomeStringValue:newValue];
// Go on to do something with oldValue
This looks reasonable, but if neither the setter nor the getter uses autorelease the "Go on to do something" part will likely crash, because oldValue has now been deallocated (assuming nobody else had retained it). You usually want to use Technique 1 or Technique 2 from Apple's accessor method examples so code like the above will work as most people will expect.
Compare this code
return [[title retain] release]; // releases immediately
with this
return [[title retain] autorelease]; // releases at end of current run loop (or if autorelease pool is drained earlier)
The second one guarantees that a client will have a non-dealloced object to work with.
This can be useful in a situation like this (client code):
NSString *thing = [obj title];
[obj setTitle:nil]; // here you could hit retainCount 0!
NSLog(#"Length %d", [thing length]); // here thing might be dealloced already!
The retain (and use of autorelease instead of release) in your title method prevents this code from blowing up. The autoreleased object will not have its release method called until AFTER the current call stack is done executing (end of the current run loop). This gives all client code in the call stack a chance to use this object without worrying about it getting dealloc'ed.
The Important Thing To Remember: This ain't Java, Ruby or PHP. Just because you have a reference to an object in yer [sic] variable does NOT ensure that you won't get it dealloc'ed from under you. You have to retain it, but then you'd have to remember to release it. Autorelease lets you avoid this. You should always use autorelease unless you're dealing with properties or loops with many iterations (and probably not even then unless a problem occurs).
I haven't seen this pattern before, but it seems fairly pointless to me. I guess the intent is to keep the returned value safe if the client code calls "release" on the parent object. It doesn't really hurt anything, but I doubt that situation comes up all that often in well-designed libraries.
Ah, ok. from the documentation smorgan linked to, it seems this is now one of the methods that Apple is currently recommending that people use. I think I still prefer the old-school version:
- (NSString *) value
{
return myValue;
}
- (void) setValue: (NSString *) newValue
{
if (newValue != myValue)
{
[myValue autorelease]; // actually, I nearly always use 'release' here
myValue = [newValue retain];
}
}