5

I'm new to objective-c and xcode and an app I'm currently writing is receiving the infamous EXC_BAD_ACCESS error.

Almost everybody recommends starting to solve the problem using NSZombies. I think I have NSZombies working but xcode isn't giving me an alert about a zombie being messaged when my app crashes.

Before I move on with my debugging, I'd like to run some code that should for sure result in a message being sent to a zombie (de-allocated object).

What is a simple code snippet where a message is sent to a deallocated object, causing a scenario where NSZombies should alert me?

Alex Crist
  • 1,059
  • 2
  • 12
  • 22
  • 1
    @zaph No, that's a memory leak. A zombie is a pointer to a deallocated object. – rmaddy Aug 14 '15 at 18:00
  • @zaph If you have zombies enabled, a zombie is what's left behind when you deallocate an object. Instead of freeing up that memory, a zombie holds that memory and can alert you when a message is sent to it -what should be a deallocated object. – Alex Crist Aug 14 '15 at 18:02
  • 1
    @zaph The whole point of a zombie (as a debugging tool) is to find cases where you have a pointer still around to an object that was deallocated and you then attempt to access the object. – rmaddy Aug 14 '15 at 18:08
  • 1
    @zaph, this question is specifically asking about NSZombie what are *you* talking about? – Mark Bessey Aug 14 '15 at 18:09
  • OK, I give to the common wisdom that a zombie can not exist without enabling zombie objects. This is rather counter to the concept of a zombie task which nomenclature I believe predates zombie objects. – zaph Aug 14 '15 at 18:22

2 Answers2

7

For non-ARC code:

- (IBAction) messageZombie:(id)sender {
    id a = [[NSObject alloc]init];
    [a release];
    NSLog(@"%@", [a description]);
}

This will give you EXC_BAD_ACCESS with Zombies off, and a "message sent to deallocated instance" message, with Zombies enabled.

If your project is using ARC, then it's a bit harder to reliably-cause messages to de-allocated objects (that is the point of ARC, after all).

This works:

- (IBAction) messageZombie:(id)sender {    
    id a = [[NSObject alloc]init];
    id __unsafe_unretained b =a;
    a=nil;
    NSLog(@"%@", [b description]);
}

It's probably not very similar to what your actual code is doing, because who the heck uses __unsafe_unretained, anyway? But if you just want to make sure that you've got NSZombies turned on properly, this should be a reasonable test case.

If you're looking for suspicious places in your code, then for sure look for __unsafe_unretained pointers, though you won't find any*, and double-check that the right casts are used for CoreFoundation objects that are casted to Cocoa objects.

* If your project needs to support OS X versions before 10.7, or iOS versions earlier than 5.0, then you can't use __weak pointers, so in that sort of project, you'd expect to find __unsafe_unretained used more often.

Mark Bessey
  • 19,598
  • 4
  • 47
  • 69
  • @MarkBessey Thanks, this is what I'm looking for, the only problem is that I have automatic reference counting enabled and I get the error: "ARC forbids explicit message send of 'release'" – Alex Crist Aug 14 '15 at 18:09
  • 4
    This may not actually crash, even with zombies off. – rmaddy Aug 14 '15 at 18:09
  • Well, if you have ARC enabled, you shouldn't have any zombies, unless you're mis-using weak pointers. Fair enough - I'll make another example for ARC code. – Mark Bessey Aug 14 '15 at 18:10
  • @MarkBessey Weak pointer mis-use is possible, I'm coming into a project that had the problem before I started. I appreciate the help. – Alex Crist Aug 14 '15 at 18:13
  • Also not mentioned is that the option "Enable Zombie Objects" must be enabled. Also to be noted is that with this setting every deallocation will leak as the memory will not be reclaimed, it is essential to remove this setting when you're done. – zaph Aug 14 '15 at 18:16
  • @zaph Very true, I do have "Enable Zombie Objects" enabled and I will ensure to disable it when I'm done debugging to prevent their inherent memory leaks. – Alex Crist Aug 14 '15 at 18:18
  • @MarkBessey Great answer, and good hint on the unsafe_unretained -there is actually shockingly large usage of unsafe_unretained pointers in the project. – Alex Crist Aug 14 '15 at 18:27
  • I should have qualified that. Old versions of iOS didn't have __weak support, so you were stuck with __unsafe_retained. If you don't have to support iOS versions before 5.0, replacing all of those with __weak might be a really good idea. – Mark Bessey Aug 14 '15 at 18:32
  • @rmaddy it's in the nature of these sorts of things that you can't actually guarantee that a particular sequence of steps will ensure that an object is in an invalid state. I could try to make that code more-reliably unreliable, but they did "work" when I tested them. – Mark Bessey Aug 14 '15 at 23:32
1

You could create a CF object, bridge it to an Objective-C object, then release it and try to use the bridged object. I think you have to use __bridge to get this to behave the way you want.

Tim Johnsen
  • 1,471
  • 14
  • 33