Catch dealloc (release) errors - iphone

I have some issues in an app that I'm developing, where sometimes if I terminate while an animation is going on, it won't end up calling the release method in the internals of the animation api.
If I do [obj release] at the end just to be safe, well it will eventually cause an internal error to be thrown if the code does work correctly and release the object.
So, my question is, is there a way to ignore these errors calling release and just continue to the next line?

There is no way to safely ignore the errors.
Understanding object retention and release semantics is one of the most important parts of writing bug-free Objective-C code. You'll save yourself a lot of these hassles if you enable automatic reference counting (ARC), but the fact is that you just can't be a serious Objective-C coder without understanding how this stuff works.
As far as the particular error, I suggest you provide some code snippets of your blocks and how you are canceling the animations, so that we can point out how to properly balance your release calls.

Related

EXC_BAD_ACCESS after convert to ARC but can profile properly with no Zombies

It's a weird situation for me that I cannot run my project on device or emulator but when I choose profile instead of run option, the app run flawlessly without any zombie guys.
It happens after I convert my project to ARC. I just modify code as Xcode tell me todo and due to the size of this project, I cannot look through every line of code.
ps. I'm the third hand on this application, so it's almost impossible for me to understand 10k lines of code.
Have you tried enabling Zombies in Xcode itself without profiling? This will set objects to never dealloc so that when you message an object that has a zero retain count, it will know what the object is and tell you. Just make sure you turn it on again so that objects will dealloc as normal.
See how to do that here:
How to enable NSZombie in Xcode?
the following can help you after the fact, but it's best IMO to perform them before migration; if a problem exists, ARC will solve some issues while abstracting others from you:
1) Create more Autorelease Pools one approach which might help you narrow things down is to explicitly create autorelease pools -- this can help localize some of your app's memory related issues. explicitly adding autorelease pools has other benefits, so this can be done not only for bug-seeking.
2) Use GuardMalloc as well, there are other memory related tools -- your app should also run fine with GuardMalloc enabled. switching to ARC could change the point of destruction -- you may be holding on to a dangling pointer.
3) Remove all Leaks finally, this may sound backwards -- remove all leaks possible. you want memory operations and lifetimes well defined. if you have an occasional leak, your issue could be hard to detect. oftentimes, reducing leaks can help you isolate the problem by making the problem easier to reproduce.

Mysterious inadequate stack traces in XCode give no context to where the error is occurring

I'm running into lots of instances with the latest version(s) of XCode (I believe this has been happening since 4.2 or so) where the stack trace when an exception is thrown is woefully devoid of details.
The screeshot here illustrates one such case; in fact, this scenario at least has SOME context (it shows me that it happened in the JKArray class), where many times I get nothing but "internal" stack items (just 2-3 entries in the thread, none of which reside in user code or anything I can look at). Even in this example, I don't know where the JKArray was allocated or released, so I have no idea what instance or where the problem is.
Thoughts:
I've tried adding a generic "on exception" breakpoint
There is some minor information available in the output; in this case: " malloc: * error for object 0x10e18120: pointer being freed was not allocated * set a breakpoint in malloc_error_break to debug". Doing this doesn't get me any further, though, since the breakpoint gets hit in the same stack as the exception...
I've tried switching to the other debugger
I've tried using my own custom exception handler
I've tried using the Profiler to look for leaks. There are no leaks that I can find.
No matter what I do, I can't seem to isolate the issues plaguing my app. Furthermore, the issues do not seem to be exactly the same each time, likely due to the high amount of concurrency in my app... so I'm left without a good way to fix the problems.
Edit: in the case of this particular exception, I did end up finding the cause. I had attempted to [release] and object that was [autoreleased]d. However, all of this was happening within my code; I can't understand why XCode would not give me a decent stack trace to help me find the problem, rather than forcing me to hunt through my whole app...
Sometimes it is impossible to pinpoint the real problem, because the issue that causes the symptom has happened much earlier.
Your issue provides a great example: when you release your object, cocoa has no idea that you've done anything wrong: you are releasing an object that you own, this is precisely what you should be doing, so there's no red flags. The code that leads to a breakdown is executed well after your method has finished, and gave the control back to the run loop. It is at this point that the run loop gets around to draining its autorelease pool, causing the second deallocation. All it knows at this point, however, is that the run loop has made an invalid deallocation, not your code. By the time the error happens the culprit is safely off the stack (and off the hook), so there is nothing else Xcode can report back to you.
A solution to problems like this is to profile your memory use: the profiler should catch issues like that, and pinpoint the places where they happen.
It goes without saying that switching to automatic reference counting will save you lots of troubles in the memory management department.

warning: received memory warning level 1 and crashes

I've been researching this throughout SO and some people said that this error is fine as long as the apps doesn't crash.
My app gets this error and after this when I try to tap on a row for a cell (calling didSelectRowAtIndexPath) it crashes. And it gives me an error UIImage sent message to deallocated message. I am guessing that this is because of the memory warning it has freed up some UIView's and therefore it crashes.
Why is this and how do I fix this? I've been debugging this for quite some time, using instruments, profiling, etc and had no luck.
I'd like to post some code, but don't know which one to post.
You have failed to retain something you cared about. From your message, I would suspect the object is a UIImage. Start by running the Static Analyzer and see if you're unretaining something obvious. Then inspect your ivars, particularly ones that are related to images. Make sure you access your ivars using accessors and not directly (except in init, the accessors themselves and dealloc). Make sure your object properties are defined with "retain".
You can use the "Zombies" instrument to help you track down which object is under-retained.
by one of your comments, it is very clear that the issue is with memory management and releasing your objects.... I suggest you to go a bit deep into your code and find out the code snippets where you are releasing you objects(or allocating them)... It can also be due to the fact that you are not at all releasing your objects after allocating and the processor trying to kill your app due to the lack of memory...And by the way, this kind of erros suck your time a lot... good luck...

Why is autorelease especially dangerous/expensive for iPhone applications?

I'm looking for a primary source (or a really good explanation) to back up the claim that the use of autorelease is dangerous or overly expensive when writing software for the iPhone.
Several developers make this claim, and I have even heard that Apple does not recommend it, but I have not been able to turn up any concrete sources to back it up.
SO references:
autorelease-iphone
Why does this create a memory leak (iPhone)?
Note: I can see, from a conceptual point of view, that autorelease is slightly more expensive than a simple call to release, but I don't think that small penalty is enough to make Apple recommend against it.
What's the real story?
(cannot accept your own answer?)
Well, after all that, I did manage to find a reference from Apple Developer, added as a side-note near the bottom of the page:
iPhone OS Note: Because on iPhone OS
an application executes in a more
memory-constrained environment, the
use of autorelease pools is
discouraged in methods or blocks of
code (for example, loops) where an
application creates many objects.
Instead, you should explicitly release
objects whenever possible.
Still, this suggests using autorelease carefully, not avoiding it altogether.
(and now for my comment)
It sounds like there is a certain amount of overhead in maintaining the pool. I read this article which would lead me to probably avoid autorelease as much as possible because I prefer things to be consistent. If you have some memory under autorelease and other memory being totally manually managed it can be a bit more confusing.
It is not the question to use or not to use autorelease, because in some cases autorelease is the only way you'll get through. The question should be "Why not to use autorelease on all objects, instead of using retain and release?".
To answer that, you should first learn what's a proper use for autorelease. Let's say that you have a class that has two properties: firstName and lastName. There is a getter and a setter for each. But you also need a method that would return fullName, by concatenating these two strings into a brand new string:
- (NSString *) fullName {
NSString str = [[NSString alloc]initWithFormat:#"%# %#", firstName, lastName];
// this is not good until we put [str autorelease];
return str;
}
What's wrong with that picture? The reference count on the returned string is 1, so if you don't want to leak, the caller should release it when he's done. From the caller's point of view, he just requested a property value fullName. He is unaware of the fact that he got a brand new object that he should release after usage, and not some reference to an NSString internally held by the class!
If we put the [str release] before return, the string would be destroyed and the method would return garbage! That's where we use [str autorelease], to mark the object for release at a later time (typically when the event processing is done). That way the caller gets his object, and does not have to worry whether he should release it or not.
The convention is to call autorelease on a new object before the method returns it to the caller. Exceptions are methods with names that start with alloc, new or copy. In such cases the callers know that a brand new object is created for them and it is their duty to call release on that object.
Replacing release with autorelease altogether is a bad idea, since the objects would pile up and clog the memory very quickly, especially in loops. The resources on the iPhone are limited, so in order to minimize memory hogging, it is your duty to release the object as soon as you're done with it.
I disagree that avoiding autorelease altogether is wise.
Cocoa Touch uses it quite frequently internally and for many situations it's the only way to allocate memory properly (a good example is reusable table view cells). If you understand what is happening, the autorelease pool is a great tool at your disposal. The main thing to remember is that the blocks are not freed until some point later in the run loop. If you are running a tight loop without user interaction and are piling up autorelease blocks, you will eventually run out of memory.
Autorelease is not a substitute for garbage collection (not available on in the iPhone SDK) and can lead to nasty dangling pointer bugs (the pointer still seems to be good, then at some unpredictable point goes invalid), but is also very useful in writing clear and easy to maintain code. Consider the following case:
[aDictionary writeToFile:
[documentsDirectory stringByAppendingPathComponent:#"settings.plist"]
atomically:YES];
The path string is generated as an autorelease object. We aren't required to create a temporary object, so we avoid that overhead (and the possibility we might forget to release it). The memory will be fully released (no leaks), just that it will happen later in the run loop. Ask yourself: am I going to allocate hundreds of these before I get back to user input? If no (as would be the case here), autorelease is a great solution and indeed this NSString method for working with paths is only available using autoreleased memory.
I do agree with the above poster that following convention and being consistent is a very good idea.
I tend to avoid using autorelease on the iPhone where I can (as Jon points out, you can't always do without it), simply because I like to know that the objects I'm working with are released the instant I don't need them. Memory constraints are one of the largest problems you'll face on the device and I believe they're the source of most of the crashing issues you'll find out there.
As highlighted by Apple, a particular area of concern is when you use autoreleased objects within any kind of loop, because they'll pile up within the autorelease pool. You then have to manage when to drain the pool or create / release one. Doing that every pass through the loop might degrade performance, but going too many passes without could lead to dangerous memory usage. I'm still tweaking this in Molecules, because there are intermittent memory issues when importing large (>2 MB) text files from the Protein Data Bank. I was able to improve performance by minimizing autoreleased objects, but couldn't eliminate them completely.
Another area to watch out for is using autoreleased objects with threads. If at all possible, do not use autoreleased objects when dealing with methods performed on a background thread, because the pool can be drained at random times. This leads to intermittent crashes that can be really fun to track down.
I would highly suggest avoiding autorelease like the plague. Memory management bugs are a great way to waste massive amounts of time and money, I've had the dubious honor of going through the process many a time on old Mac apps, and the fact that the iPhone has tight memory constraints mean that you have to be extremely careful, or the app will just be unstable and crash often...like so many of the first apps that were released last summer.
The only reliable way I've found to write stable iPhone applications is to manage all your memory yourself, and do it consistently. Even if you are the only programmer on your project, you'll thank yourself later. It can be difficult if you learned to program in languages that "take care of everything for you," but it really is worth learning how to do well if you are serious about createing quality iPhone apps.

Autorelease iPhone

Coming up towards the end of developing an iPhone application and I'm wondering just how bad is it to use autorelease when developing for the iphone. I'm faced with some fairly random crashes and, so far, I can't pinpoint it to anything other than sloppy memory usage.
As a Cocoa newbie I remember initially reading a guideline document that strongly suggested avoiding autorelease in favor of manual retain/release for iPhone. However, a more 'senior' Cocoa developer came on board early on (who ironically has been let go since), who used autorelease all over the place. Admittedly, I was went into "monkey see monkey do" mode, and it appears to be coming back to haunt me (I'm now the only developer on the project).
So what to do next? It seems to me that I have to branch the code and try to go through and replace, where possible, autorelease code keeping my fingers crossed that I don't inadvertently break the app. It seems a lot of library calls result in autoreleased objects like stringWithFormat and pretty much anything where I'm not using alloc myself. Any other gotchyas and/or suggestions I should be looking out for? Thanks Cocoa gurus.
Using release instead of autorelease can improve memory usage in tight spots (which is good on the iPhone), but it's not going to help at all with crashing if you're not following the retain / release rules. I would read a few tutorials on memory management in Obj-C if you're still a little hazy on what you should be doing, and then go after those crashes using the debugger and crash reports to find out where you're over releasing objects. This and this are two good places to start.
More important than the autorelease or manual-release choice is how often you alloc and dealloc your NSAutoreleasePools. Since most of the Cocoa frameworks use autorelease liberally, you need to have a proper pool draining strategy. Once that is in place, the choice of whether to release or autorelease becomes much less an issue.
That being said, the only areas you should worry about are tight loops--allocate and release an NSAutoreleasePool every few iterations for best results; and when you have spawned another NSThread that doesn't have a Runloop--create a pool and drain it every so often becomes idle. Since most applications only allocate a small amount of data per event, UIKit's strategy of allocating the pool before the event is dispatched and releasing it after the dispatch returns works very well.
If you think you dunno how to use autorelease, check out CS193p FALL 2010 on iTunes U -> Lecture number 4.
It teaches you all about memory management and stuff (if you skip the first 10 minutes or so)
For iPhone performance reasons, Apple suggest that, whenever possible, you shouldn't use autoreleased objects. Instead, explicitly release your objects when you are done with them.
Using autorelease pools means that you might be leaving some unused memory lying around. Since the iPhone has less memory to go around, you might improve performance if you free up unneeded memory as soon as possible, rather than letting it sit around taking up resources while it waits for an autorelease.
When you autorelease, you're basically saying: "I don't need this any longer, but anyone else is free to pick it up (before the auto release pool is drained)". When you explicitly relase an object you're saying: "I don't need this any longer and unless anyone else has already said otherwise (acquired), it should be deallocated immediately."
Consequently, autorelease is not normally the wrong thing to. It is required when you want to pass objects back to the sender of a message without requiring the sender to take care of releasing the object.