iphone memory management issue - iphone

How to check if an object has been released from the memory?
I know a object has to be released manually when we use alloc|copy|retain to create that object. if use the instance class method (NSString stringwithformat:), the object will be released automatically by NSAutoRealeasePool, however, sometime there have some object used to release at the (void)dealloc function there.
Can anybody tell me
What is the difference between [object release] instantly after alloc function, [object release] at (void)dealloc,and NSAutoReleasePool to release the object?
When is the (void)dealloc function being called and when is the NSAutoReleasePool release the memory, I know it is every loop cycle, how can I check it from code?
When I declared a variable in the header and set the property as retain, I still can use the alloc function to that object but not cause a memory leak, but from this post it seems like once declared a retain object at header, then you no longer can alloc the object because both will retain the object,can anybody tell me why I still can code like this without causing any memory leak?

[object release] releases your object immediately. After sending a release message you should not use the object again - unless you absolutely know you still have a retain on that object. If yours was the last retain the memory could be freed during the call to release.
Autorelease frees an object 'sometime later' the system does not guarantee anything about the meaning of 'later' other than that it will be after the scope of the current message.
See above, there is no real qay to guarantee when dealloc is called following autorelease from the point of view of your code. You should just assume it is sometime after the return of the method where you send the autorelease message.
You simply need to balance retain and release. If you have one to many (as is likely i nthe situation you describe) that is a leak. Conversely if you have unbalance the other way, you will generate a more destructive error when you access freed memory.
The correct sequence for a retained property is:
alloc init // retain == 1
set the property // retain == 2 due to setProperty calling retain.
release the object // retain == 1
Which leaves a retain count of one, no memory leak.

Related

what is the difference between release and auto release and is there any way to create a user defined autorelease pool? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is the difference between releasing and autoreleasing?
Hi can you please elaborate what is the difference between release and auto release and is there any way to create a user defined autorelease pool?and the real use of auto release pool.
Release reduces the object's reference count immediately, which means that if its retain count reaches zero it'll be immediately deallocated. Autorelease is a delayed release -- it's useful for ownership handoffs.
Consider a method like +[NSString stringWithFormat:]. It creates a new NSString instance (with alloc & some form of init) and then hands it off to the caller. That class method doesn't want to still "own" the created string after that, but if it releases the new string before returning, the new string will get deallocated before the caller gets it. Instead, it autoreleases the new string: that means the string will stick around long enough for the caller to grab it and retain it if needed.
What happens if the caller doesn't retain it? That's where autorelease pools come into play. The NSAutoreleasPool keeps track of every autorelease, and when told to drain, it releases all the objects in its pool (causing them to get deallocated if their reference count goes to zero). By default in a Mac or iOS app, there's an autorelease pool in the main event loop -- so if you call stringWithFormat: and don't retain the result, it'll go away on the next pass.
You can create your own autorelease pool with NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init] and drain it with [pool drain]. This can be useful if you have a section of code where you're creating a lot of temporary objects.
release releases the object immediately while autorelease does it some time in the future.
Example: You'd want to return an autoreleased object here, because if you'd release it, it would already get dealloc before the code calling this method can make use of the returned object!
- (NSObject *)someMethod
{
return [[[NSObject alloc] init] autorelease];
}

Objective-C pointers/memory management question

I am testing the following code below. ffv is declared in the interface file.
ffv = [[FullFunctionView alloc] initWithFrame:self.view.bounds];
NSLog(#"%i", [ffv retainCount]); // prints 1
[self.view insertSubview:ffv belowSubview:switchViewsBtn];
NSLog(#"%i", [ffv retainCount]); // prints 2
[ffv release]; // you can release it now since the view has ownership of ffv
NSLog(#"%i", [ffv retainCount]); // prints 1
if (ffv == nil)
NSLog(#"ffv is nil");
// "ffv is nil" is not printed
[ffv testMethod]; // "test method called" is printed
this is my [ffv testMethod] implementation
- (void)testMethod
{
NSLog(#"test method called");
}
What I deduce in this case is that even if you release an object with retain count 2, you lose ownership of that object however, the reference is still kept.
Now, my question are:
Is my deduction correct?
Is there anything else important that can be deduced from this?
What are the complications caused by still keeping (using) ffv and calling methods from ffv? (My opinion is that this is ok since the view will always own ffv and won't release it until someone calls viewDidUnload. And as long as I don't pass ffv's reference to other objects.)
There are a couple of problems with using ffv after you have released it and it's only retained by your view controller's view.
1) It introduces a potential for future bugs, because later you might not remember that ffv is otherwise not retained. When you release the view (e.g. by replacing it with another view), you have a dangling pointer that you still hold a reference to.
2) In the special case of a UIViewController the view could be released at any time (you usually never call viewDidUnload yourself). The default behavior of UIViewController, when receiving a memory warning and the view is currently not visible, is to release the view, so unless you set the reference to nil in viewDidUnload, you have a dangling pointer again, even though you never explicitly released the view yourself.
1) Is my deduction correct?
Your deduction is correct. The Memory Management Programming Guide explains that each object has one or many owners. You own any object you create using any method starting with alloc, new, copy, or mutableCopy. You can also take ownership of an object using retain. When you're done with an object, you must relinquish ownership using release or autorelease.
Releasing the object doesn't change the value of any variables that reference that object. Your variable contains the object's memory address until you reassign it, no matter what retain count the object has. Even if the object's retain count goes to zero, causing the object to get deallocated, your variable will still point at that same address. If you try to access the object after it's been deallocated, your app will normally crash with EXC_BAD_ACCESS. This is a common memory management bug.
2) Is there anything else important that can be deduced from this?
Nothing comes to mind.
3) What are the complications caused by still keeping (using) ffv and calling methods from ffv? (My opinion is that this is ok since the view will always own ffv and won't release it until someone calls viewDidUnload. And as long as I don't pass ffv's reference to other objects.)
When you call release, you are telling the Objective C runtime that you no longer require access to the object. While there may be many cases like this one in which you know the object will still exist, in practice you really shouldn't access an object after calling release. You'd just be tempting fate and setting yourself up for future bugs.
I personally don't like peppering my code with release statements, because I don't trust myself to remember them 100% of the time. Instead, I prefer to autorelease my variables as soon as I allocate them like this:
ffv = [[[FullFunctionView alloc] initWithFrame:self.view.bounds] autorelease];
This guarantees that ffv will exist at least until the end of the method. It will get released shortly thereafter, typically before the next iteration of the run loop. (In theory this could consume excessive memory if you're allocating a large number of temporary objects in a tight loop, but in practice I've never encountered this case. If I ever do, it will be easy to optimize.)
The object is not deallocated until the retain count goes to 0. As long as it's not deallocated, you can keep using it without trouble. By retaining it you ensure that it won't be deallocated under your feet; however, if you retain another object that you know retains the first object, you can get away with this form of "indirect retaining". Don't complain when you move things around later and things start breaking, though.
if (ffv == nil)
NSLog(#"ffv is nil");
// "ffv is nil" is not printed
That's correct, releasing an object does not set the pointer to nil even if it is dealloced at that time. Good practice is to always set your pointer to nil after you release it.
You are correct to say that after you released it, it wasn't dealloced because the view still had a retain on it. But that's not how you should be thinking about it. If you want to use that object and you want it to be alive, retain it. Doesn't matter who else is retaining it. Your object has nothing to do with those other objects. You want it, retain it. You're done with it, release it and set your pointers to nil. If you don't set it to nil and everyone else also released it, you will have a dangling pointer to an object that was dealloced, and that will cause you a crash and much grievance.
so this:
[ffv release]; // you can release it now since the view has ownership of ffv
ffv = nil; // you released it, so that means you don't want it anymore, so set the pointer to nil
if you still want to use it, don't release it until you're done with it.
Well, I'm not sure 'losing' ownership is the right term. In Objective-C you have to carefully marshal your ownership of the object. If you create or retain an object, you are responsible for releasing it (either directly or via an autorelease pool). When you call release however, you don't lose a reference to the object, if something else has retained it, it will still be in memory, and your pointer will still potentially point to it.
You have a pointer ffv which is just a pointer to some memory, and you have the object which is created in the first line that ffv points to.
By calling release, you are stating that you no longer require the ponter ffv to point to a valid object, that in this context you would be happy for the object to be deallocated. The pointer still points to that bit of memory, and it is still there because its retain count was increased by assigning it to the view.
The line [ffv testMethod] is in danger of not working, as it follows the release and may not point to a valid object. It only works because something else is keeping it alive. ffv still has the same address value that it had when it was first assigned.
So in order:
Your deduction is correct.
Not really.
You shouldn't use ffv after the release call. You have no guarantee that the object is going to be there for you.
These are pointers we are using here, not references like you find in Java or C#. You have to marshal your ownership of the object, you create it, have some pointers to it and by careful management of retain and release calls you keep it in memory for as long as you need it.

My block is not retaining some of its objects

From the Blocks documentation:
In a reference-counted environment, by
default when you reference an
Objective-C object within a block, it
is retained. This is true even if you
simply reference an instance variable
of the object.
I am trying to implement a completion handler pattern, where a block is given to an object before the work is performed and the block is executed by the receiver after the work is performed. Since I am being a good memory citizen, the block should own the objects it references in the completion handler and then they will be released when the block goes out of scope. I know enough to know that I must copy the block to move it to the heap since the block will survive the stack scope in which it was declared.
However, one of my objects is getting deallocated unexpectedly. After some playing around, it appears that certain objects are not retained when the block is copied to the heap, while other objects are. I am not sure what I am doing wrong. Here's the smallest test case I can produce:
typedef void (^ActionBlock)(UIView*);
In the scope of some method:
NSObject *o = [[[NSObject alloc] init] autorelease];
mailViewController = [[[MFMailComposeViewController alloc] init] autorelease];
NSLog(#"o's retain count is %d",[o retainCount]);
NSLog(#"mailViewController's retain count is %d",[mailViewController retainCount]);
ActionBlock myBlock = ^(UIView *view) {
[mailViewController setCcRecipients:[NSArray arrayWithObjects:#"test#recipient.com",nil]];
[o class];
};
NSLog(#"mailViewController's retain count after the block is %d",[mailViewController retainCount]);
NSLog(#"o's retain count after the block is %d",[o retainCount]);
Block_copy(myBlock);
NSLog(#"o's retain count after the copy is %d",[o retainCount]);
NSLog(#"mailViewController's retain count after the copy is %d",[mailViewController retainCount]);
I expect both objects to be retained by the block at some point, and I certainly expect their retain counts to be identical. Instead, I get this output:
o's retain count is 1
mailViewController's retain count is 1
mailViewController's retain count after the block is 1
o's retain count after the block is 1
o's retain count after the copy is 2
mailViewController's retain count after the copy is 1
o (subclass of NSObject) is getting retained properly and will not go out of scope. However mailViewController is not retained and will be deallocated before the block is run, causing a crash.
Do not use -retainCount.
The absolute retain count of an object is meaningless.
You should call release exactly same number of times that you caused the object to be retained. No less (unless you like leaks) and, certainly, no more (unless you like crashes).
See the Memory Management Guidelines for full details.
(cribbed from one of #bbum's answers)
As for your question:
Are you actually observing a crash? Or are you just shooting blindly from the hip and thinking that it might crash?
From the code you posted, it would appear that mailViewController is an instance variable, in which case the block would be retaining self instead of the instance variable. And since you autoreleased your instance variable, it's getting cleaned up by an NSAutoreleasePool just like you'd expect.
So in summary:
Do not use -retainCount.
Do not autorelease instance variables that you want to exist beyond this turn of the run loop.
edit A bit more clarification:
Here's what's going to happen when your block is created:
Inspect object references in its scope. There are two: self->mailViewController and o.
self->mailViewController is a member of a struct (self), so it is not retained directly. Retain self instead.
o is a local variable. Retain it.
This is proper behavior. As for your code...
o is created with a +0 retain count
self->mailViewController is created with a +0 retain count
myBlock is created with a +0 retain count. o now has a +1 RC, as does self. self->mailViewController still has a +0 RC
myBlock is copied => +1 retain count
Fast forward to the end of this run loop cycle.
The current autorelease pool is drained. All objects with a +0 retain count are deallocated, including self->mailViewController. self->mailViewController now points to deallocated memory, and is essentially garbage.
Fast forward to some future point when myBlock is executed
myBlock attempts to invoke a method on self->mailViewController. However, self->mailViewController no longer points to a valid object, and your app crashes.
However, if mailViewController is not an instance variable, then we need to see more code. I think it'd be highly unlikely that the behavior you're seeing is a problem with the blocks runtime, but it is possible.
The documentation no longer says that. It now correctly says:
In a manually reference-counted environment, local variables used
within the block are retained when the block is copied.
As the "mailViewController" is a member of your current class instance, so the block actually retain "self" here.

NSArray release crashes with EXC_BAD_ACCESS

Another puzzler. I have an NSArray (iTours) containing 3 Objects and a retain count of 1.
This Array is released in the object dealloc method as follows:
- (void)dealloc {
NSLog(#"retain count für iTouren: %d", [iTours retainCount]);
[iTours release]; // triggers EXC_BAD_ACCESS
[super dealloc];
}
The console window shows the following message (no further details):
Program received signal:
“EXC_BAD_ACCESS”.
any clues what's going on? What did I miss?
Most likely, you are over-releasing iTouren and, thus, that call to release is causing the crash. That is, iTouren is already deallocated by the time you release the containing array and when that containing array sends release to the already deallocated iTouren your app crashes.
(Of course, iTours might be the object that is already deallocated. In any case, it is an over-release problem.)
Turn on zombie detection and see if that barfs up the specific problem.
Note that the number returned by retainCount is useless. Absolute retain counts are an implementation detail and will often be a specific value that seems like nonsense.
In this case, the final release of an object does not decrement the retain count. Why? Because that'd be a wasted cycle when the object is about to be deallocated anyway. It would be impossible for retainCount to return 0 because, by definition, an object with a retain count of 0 has already been deallocated and, thus, is no longer a viable message receiver anyway.
Never, ever, ever, rely on the retainCount method.
Ever.
Did I mention ever?
One is iTours the other one iTouren. You are logging a different object than that being released.
Assuming iTours and iTouren are different objects (namely that iTours is an NSArray containing iTouren), you've over-released iTours; maybe you had a failure in a setter and iTours was released without being reassigned and retained.
Be sure that your array does not contains itself. Releasing an array also release every object in it. Of course, if this is the case, the array should have a release count of two before you release it because arrays retain their elements.
A released and deallocated object will have a retain count of 1. A non-released object about to be released and deallocated will also have a retain count of 1. (Assuming memory is ever allocated for the object, some strings and numbers are never allocated, implementation detail that changes per Mac OS X release)
When an object is deallocated in current versions of Mac OS X, the memory is marked as free, nothing about the object is modified (unless you tell it to be). Thus, the retain count remains identical to the retain count before it was released.
This is the make a mistake and DIAF approach that help makes Mac OS X so solid.

How are objects in an autorelease pool referenced?

I am wondering if the autorelease pool holds strong or weak references to the objects it holds. I would guess they are weak. When I add an object to an autorelease pool, it's just not immediately released but will be released when the pool is drained, right? So the references should be weak, i.e. the reference count (or retain count) keeps the same when I add an object to an autorelease pool?
Talking of strong versus weak references makes sense in the context of a garbage collected memory management environment (where weak pointers are automatically released and cleared even if referenced). With GC enabled, all retain/release/autorelease calls are essentially do nothing operations (though the NSAutoreleasePool -drain method triggers garbage collection).
Now since you've tagged this question as iPhone related, and there's no garbage collection on iPhone, I'm assuming you're referring to regular reference counting, by strong you mean increasing the retain count of the referenced object, and by weak you mean just storing the pointer value.
The autorelease method essentially moves ownership of an object from the calling code to the current autorelease pool, you can think of the calling code calling release and the pool calling retain.
So the reference is effectively strong, but your code loses ownership and release responsibility. Object release will be called when the autorelease pool is released/drained.
The whole point of the autorelease pool is that it is a deferred release. For example, you can call autorelease on a local object you will be returning in a method so that it gets released even though you lose the reference to the object when the method returns.
Yes. retain count keeps the same, and yo can can check, that it is so:
id obj = [[NSObject alloc]init];
NSLog([NSString stringWithFormat: #"%d", [obj retainCount]]);
[obj autorelease];
NSLog([NSString stringWithFormat: #"%d", [obj retainCount]]);
The retain count remains the same, basically firing an autorelease message on an object makes the developer free from having the ownership and release responsibility.
This is how autorelease pool works-
Every time an instance of autorelease pool is created, it's added on top of the stack, so the most recent autorelease pool will be used by the system. And whenever you add any object in the autorelease pool, it's added on the top autorelease pool in the stack. An autorelease pool is basically an array on which the autoreleased objects are added. Every object added in autorelease pool is released when that particular autorelease pool is released(/drained). An autorelease pool is created first before the system starts processing any event, and it remains there till the current event loop's execution is over. When system see's that current event loop is completed then it get's the topmost autorelease pool associated with that event loop and releases it. Releasing an autorelease pool/ draining means getting each object added in autorelease pool and firing a release message on object, till all the objects in autorelease pool are released.