NSZombieEnabled hides EXC_BAD_ACCESS error entirely - iphone

So I have a subclass of a UIView that starts causing EXC_BAD_ACCESS errors when I go through a specific set of conditions (run on iPad instead of iPhone or simulator, first login only). It throws the exception when the UIView subclass gets autoreleased from the pool (i.e. the pool is releasing, not when I'm calling [view autorelease], during the last line, where I have [super dealloc]. I heard about using NSZombieEnabled, so I tossed that on to see if I could get any more information about it, but now it hides the error completely!
Does anyone know a bit more about this type of situation? I thought NSZombie would start spewing stuff into my console like before, but I'm hoping that the nonexistance of errors would tell me some sort of information as well.
- (void)dealloc
{
[loadingLabel release];
[indicatorView release];
[super dealloc];
}
Edit: Ok, so I sorta solved the underlying problem:
One of my properties was:
#property (nonatomic,retain) NSString * title;
However, the code for that property is as follows (loadingLabel is a UILabel):
- (void)setTitle:(NSString *)title
{
loadingLabel.text = title;
[loadingLabel sizeToFit];
[self setNeedsLayout];
}
- (NSString *)title
{
return loadingLabel.text;
}
I don't actually retain anything, but rather only do a UILabel.text, which is a copy property. So I changed my own title property to reflect this, and the error has disappeared.
However, I still don't really know how or why this error popped up in the first place, and why it only appears on the iPad platform (not the iphone, or even the ipad simulator).

So I have a subclass of a UIView that starts causing EXC_BAD_ACCESS errors when I go through a specific set of conditions (run on iPad instead of iPhone or simulator, first login only). It throws the exception when the UIView subclass gets autoreleased from the pool (i.e. the pool is releasing, not when I'm calling [view autorelease], during the last line, where I have [super dealloc]. I heard about using NSZombieEnabled, so I tossed that on to see if I could get any more information about it, but now it hides the error completely!
You get EXC_BAD_ACCESS because you tried to work with a dead object.
NSZombieEnabled makes objects not die. Since the object never died, your app didn't crash. Instead, you'll get a message in the Console log (the Debugger Console when running under Xcode), telling you what you did wrong and suggesting a breakpoint to set.
To be more specific, the NSZombie message will tell you what class of object you sent a message to, and what message you sent it. If you set the breakpoint and run your app with the debugger active, the debugger will interrupt (“break”) your app at that point, so that you can look around and see what sent the zombie object the message.
I don't actually retain anything, but rather only [assign to] a UILabel.text, which is a copy property.
Thus, the string presumably died off for not being owned by anything. With NSZombieEnabled and the above technique, you can confirm the theory that it was the string that was dying off prematurely.
A better and easier way, though, is to use Instruments's Zombies template. Instead of a message appearing in Xcode's Debugger Console, a flag in will appear Instruments's timeline with the information. That flag will have a go-to-iTunes-Store (➲) button you can click for more information about the problem.

Could you clarify - do you mean that you throw an EXC_BAD_ACCESS exception or you (on purpose) cause the system to throw an EXC_BAD_ACCESS exception? How do you do this? Please show some code. NSZombie will spew to the console if you try to call an instance method on it. Are you doing that?

NSZombie should produce output to the console in the same location a crash would have occurred.
Have you tried also running Instruments with the ObjectAlloc tool, and enabling both retain count and zombie detection in there (you need it both in the executable and configure the ObjectAlloc instrument, click on the "i" next to ObjectAlloc). When a message is sent to a zombie that instrument will flag you with a special popup saying a zombie was detected.

Remember the iPad SDK is still beta, maybe you should report this but to apple if you can confirm this to be a bug. Unfortunately their bugtracker is horrible from my experience.
The behavior of NSZombie is to never decrease an objects retain cound if release is called. However it keeps track of the would-be retain count and logs acess to the object after it would have been deleted on the console. It puts the Object adress alongside the error message, together with Instruments you can easily locate the Object at that adress and determine where it has been alocated and who retained/released it.

Related

Unable to find Zombie in Instruments for device

Unable to find Zombie in Instruments for device .
I am able to find Zombie in Instruments for Simulator but not able to find for device , my app only run on device due to addition of third party api.
How can i trace cause of crash due to "message sent to deallocated instance "
I just want to find exact instance(or line of code) which is causing this crash.
Although, when XCode returns "Message sent to deallocated instance" error message, it normally tells the Object as well which is sending that error.
Anyway, you can use the below to find the exact line which is causing you the error:
Use Exception BreakPoint for All Exceptions in XCode.
To Add an Exception Breakpoint:
1. Go to BreakPoint Navigator
2. At the bottom there is a plus symbol. Click it.
3. You will get two options: Add Exception Breakpoint... and Add Symbolic BreakPoint...
Choose Exception Breakpoint.
Some reasons for zombies crash:
1. Control delegate response late after the control instance is cleared.
2. Instance used inside the thread try to modify the instance after its get cleared.
So handle the delegate properly
Make control delegates to nil while removing view controller like this:
- (void)viewDidDisappear:(BOOL)animated
{
[self.mapView setDelegate:nil];
[_webView setDelegate:nil];
}

app crashes without any log messages

In my App I have an UIViewController, that pushed by another ViewController's navigation controller. It contains some views, buttons, scrollViews and accelerometer support. When I tapping "back" button of navigationController, app crashes without any log message, except this one:
"warning: Unable to read symbols for /Developer/Platforms/iPhoneOS.platform/DeviceSupport/4.3.3 (8J2)/Symbols/Developer/usr/lib/libXcodeDebuggerSupport.dylib (file not found).
(gdb)"
debugger links me to this line in main.m:
int retVal = UIApplicationMain(argc, argv, nil, nil);
with "EXEC_BAD_ACCESS"
what does this mean?
EDIT:
all of you are right.
problem was in accelerometer. I setted delegate ([UIAccelerometer sharedAccelerometer].delegate = self;) and didn't remove it. that's why there was no line in my code for debugger to link to. I just added this:
- (void)viewWillDisappear:(BOOL)animated {
[UIAccelerometer sharedAccelerometer].delegate = nil;
}
and problem gone. So, If you are using any device functions, be careful with delegates.
Did you set Zombies to enabled? That will enable you to track if you access an already released object, and that tells you which object it is.
If you are using XCode 4, you can enable zombies in Project -> Edit Scheme -> Diagnostics by checking the "Enable Zombies" checkbox.
Also make sure you have "Break on Exception" set on - in XCode 4 go to the Breakpoint View, press the Plus sign in the lower left corner, and choose "Add Exception Breakpoint ..." for all exceptions. Then XCode will break at the point where the exception occurs, and you will see more than just UIApplicationMain as the location.
This means you have tried to read/write a block of memory you have no permission to. Maybe you're trying to use an object you haven't allocated/initialized. Check your code, debug it and inspect variables to find a solution.
I guess you had a memory warning and you app deallocated some datas tha are not there anymore when you go back.
Put some breakpoint into didReceiveMemoryWarning, dealloc, viewDidUnload and viewDidLoad to see what happens in your previous controller.
EXC_ BAD_ ACCESS is an exception (EXCeption_ BAD_ ACCESS).
If you set a breakpoint on objc_exception_throw (sign + on the lower left corner of debug tab), you'll get those.
You might want to look at NSZombieEnabled (http://www.cocoadev.com/index.pl?NSZombieEnabled), as you're probably trying to access a dealloc'd object.

iPhone: Zombie object in modalview and delegate

I have a crash in my App that sometimes occurs, I tested with zombies enabled and this method it found as a ZOMBIE, this method usually works OK but in some conditions like lots of navigate back and forth at somepoint it crashes.
I retain the datepickerView in #property and release it in deaaloc.
Set the datePickerDelegate to nil in dealloc. If it has a retain property after the first instantiation the delegate will probably have a dead reference in it and will randomly cause creates and crashes when Zombies are enabled. The crash happens because retain properties release the previous value and if it is a dead reference crashes ensue -- randomly. Also best to set delegates to assign, not retain.
Run in instruments, in Allocations set "Record reference counts" on on (you have to stop recording to set the option). Cause the picker to run, stop recording, search for there ivar (datePickerView), drill down and you will be able to see where all retains, releases and autoreleases occurred.
I see no reason to keep the picker in memory after it has been popped from stack...
Instead of retaining the DatePickerController, remove "autorelease", and "release" just after presentSemiModalViewController, as per reednj post on SemiModelDatePicker
TDDatePickerController* datePickerView = [[TDDatePickerController alloc]
initWithNibName:#"TDDatePickerController"
bundle:nil];
datePickerView.delegate = self;
[self presentSemiModalViewController:datePickerView];
[datePickerView release];
Hopefully this will alleviate the problem. Otherwise, it could simply be a problem with the SemiModalDatePicker extension.

How can I tell if a referenced object has been deallocated in objective-c?

After upgrading to iPhone OS 4.0 the application started to crash after switching between applications. The application crashes in the same place when the application receives a memory warning.
It seems like some objects are automatically deallocated when a memory warning is received and then when we try to use the deallocated objects the application crashes.
Is it possible to test if an object has been deallocated, so that we can reallocate them?
You can't test whether a specific object has been deallocated because after deallocation, the object no longer exist. The only thing you can do is test whether a reference to the suspected object from another object is still non-nil.
Your problem here isn't deallocation per se but rather mismanaged retention. You have an object that has been marked as no longer being in use and the system is killing it as the system should. The only reason that you see it during low memory is that the system stops and drains all the release pool instantly instead of waiting for the normal cycle.
You need to make sure you have properly retained all the objects you need so they won't be improperly released. A retained object is not deallocated even in low-memory situations.
Edit
I would add that the most common cause of low-memory crashes is assuming that a view or a resource in a view is always present even when the view is not displayed. The system will purge undisplayed views and their resources (like images) in low-memory. Check the didReceiveMemoryWarning of the view controllers.
You can add
-(void)dealloc { ... }
And leave it empty if it's the right to do, and add breakpoint in it.
This answer correct to ARC and NON-ARC
Implement the method dealloc inside a UIViewController to see the moment it is being released from memory
- (void) dealloc
Print the reference of any object you want to test.
NSLog("Get pointer: %#", self); // ViewController
Then set a break point at a place where you want to test if the object is still existing. If you ran into the breakpoint, check the objects pointer in the debugger with
`po [pointer_printed_before]
Here you can see, the pointer is not available anymore, there is no object anymore after the dealloc method printed a log.

iPhone Simulator crash with WebPreferences in the thread list

Apple Developer Reference Library has a class reference for WebPreferences
I've searched SO, Dev Forums and Googled without any relevant results.
EXC_BAD_ACCESS signal is generated.
I can't find a crash report.. its happening on the simulator. The debugger is called, and I don't get a crash report.
EDIT
This is triggered when tapping a UITextField, leaving a UITextField or if a UITextField is set as first responder when loading a view (push on by a navigation controller).
It is not easy to reproduce. I can go for a hundred app-launch/debug cycles before it will happen again. And then it might happen 3 times in 5 launches.
I do have a thread list in the debugger that shows several references to WebPreferences.
You're on the right track if you are using NSZombie. EXEC_BAD_ACCESS is caused by accessing released objects.
It is normal for EXEC_BAD_ACCESS to "crash" in code paths that do not belong to you. Most likely your code created the over-released object.
The key part of using NSZombie is running the malloc_history on the command line. You'll get the call stack showing where the over-released object originated from. For example:
alt text http://static.benford.name/malloc_history.png
The screenshot shows my app crashing at [NSString stringByTrimmingCharactersInSet:] but that is certainly not who caused the crash.
I technique I use is to look at the earliest code path that you own. Most of the time the mistake lies there.
In this case, the object originated from the class [JTServiceHttpRequest requestFinished], in which I was not properly retaining a object.
If all else fails, go through all your code paths listed and verify your use of proper memory management rules.
My bet is that WebPreferences and UITextField behavior have nothing to do with the crash.
For any EXC_BAD_ACCESS errors, you are usually trying to send a message to a released object. The BEST way to track these down is use NSZombieEnabled.
This works by never actually releasing an object, but by wrapping it up as a "zombie" and setting a flag inside it that says it normally would have been released. This way, if you try to access it again, it still know what it was before you made the error, and with this little bit of information, you can usually backtrack to see what the issue was.
It especially helps in background threads when the Debugger sometimes craps out on any useful information.
VERY IMPORTANT TO NOTE however, is that you need to 100% make sure this is only in your debug code and not your distribution code. Because nothing is ever released, your app will leak and leak and leak. To remind me to do this, I put this log in my appdelegate:
if(getenv("NSZombieEnabled") || getenv("NSAutoreleaseFreedObjectCheckEnabled"))
NSLog(#"NSZombieEnabled/NSAutoreleaseFreedObjectCheckEnabled enabled!");
If you need help finding the exact line, Do a Build-and-Debug (CMD-Y) instead of a Build-and-Run (CMD-R). When the app crashes, the debugger will show you exactly which line and in combination with NSZombieEnabled, you should be able to find out exactly why.
The fact that it's crashing in _integerValueForKey: makes me strongly suspect that it's crashing on an over-released NSNumber. Over-releasing an NSNumber can lead to such bizarre crashes that it's almost humorous. Here's what happens:
You create a NSNumber for the integer "2"
The NSNumber class caches the NSNumber
You over-release it
The NSNumber class's cache now points to bad memory
Some completely unrelated piece of code creates an NSNumber for the integer "2"
The NSNumber class looks it up in its cache, and....
Bang
If you're running Snow Leopard, hit Cmd-Shift-A to let the analyzer look for memory management problems. Otherwise, go hunting in your use of NSNumbers.
agreed with previous responders about NSZombie. Most often this thing happens when you use your class as a delegate of a UITextView(or any else class) and also refer it in IBOutlet variable. when you leave your viewcontroller - it become deallocated. but if you didn't release IBOutlet variable in - (void) dealloc method - UITextView will still send calls to released delegate (your view controller).
Sounds more like an Auto-Release bug. You might be releasing something you don't "own" and the NSAutoRelease pool is running and trying to clean up something that was already released?
Did you release something you didn't "alloc"? For example, you wouldn't do:
NSString *test = #"testing";
[test release];
As this will cause the crash to happen when the Auto Release pool runs and attempts to release the NSString.