views:

490

answers:

4

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).

A: 

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?

mustISignUp
Whoops, bad choice of words I suppose. The view is finally deallocing due to an autorelease, and the BAD ACCESS exception pops out during the [super dealloc] part. However, this exception does not appear whatsoever when NSZombie is enabled. I was under the assumption that NSZombie would spew to the console in these circumstances. Is this not correct?
David Liu
You are correct. if i do [[[NSObject new] autorelease] release]; i See the message " *** -[NSObject release]: message sent to deallocated instance 0x100208580" which is more useful than "Program received signal: “EXC_BAD_ACCESS”." that i get if zombies is off.
mustISignUp
mustISignUp: That's nothing to do with zombies, though. It all depends on timing: If something allocates and writes over the memory formerly occupied by the object before you send it a message, you'll get a bad-access crash. If nothing has done that yet, you'll get the “message sent to deallocated instance” message. That's true even when NSZombieEnabled is turned off.
Peter Hosey
Peter Hosey: No, i do not see the “message sent to deallocated instance” message without NSZombie enabled. Have you actually tried this?
mustISignUp
Yes, but not recently enough, apparently. They changed NSZombieEnabled's log message, perhaps in Leopard; it used to say “break at -[_NSZombie release] to debug” (shown in full at http://www.omnigroup.com/mailman/archive/macosx-dev/2004-April/052250.html). I remember receiving reports of “message sent to deallocated instance” from users, which is why I thought those were not produced by zombies, but I've just gone through them all and they all say that the user ran the program with NSZombieEnabled. So, I was wrong; “message sent to deallocated instance” is the zombie message. I'm sorry.
Peter Hosey
A: 

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.

Johannes Rudolph
A: 

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.

Kendall Helmstetter Gelner
A: 

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.

Peter Hosey
You're misunderstanding my problem.I realize that NSZombieEnabled makes objects not die, and will (should) spew a message out to the Console Log when the object is accessed incorrectly after it's "dead".However, my problem is that with NSZombiesEnabled instead, nothing shows up in the Console log, or in Instruments.
David Liu