views:

658

answers:

2
Program received signal:  “EXC_BAD_ACCESS”.
(gdb) bt
#0  0x30011940 in objc_msgSend ()
#1  0x30235f24 in CFRelease ()
#2  0x308f497c in -[UIImage dealloc] ()
#3  0x30236b78 in -[NSObject release] ()
#4  0x30a002a0 in FlushNamedImage ()
#5  0x30250a26 in CFDictionaryApplyFunction ()
#6  0x30a001a4 in _UISharedImageFlushAll ()
#7  0x30a00738 in +[UIImage(UIImageInternal) _flushCacheOnMemoryWarning:] ()
#8  0x3054dc80 in _nsnote_callback ()
#9  0x3024ea58 in _CFXNotificationPostNotification ()
#10 0x3054b85a in -[NSNotificationCenter postNotificationName:object:userInfo:] ()
#11 0x3054dbc0 in -[NSNotificationCenter postNotificationName:object:] ()
#12 0x30a00710 in -[UIApplication _performMemoryWarning] ()
#13 0x30a006a8 in -[UIApplication _receivedMemoryNotification] ()
#14 0x30a005d8 in _memoryStatusChanged ()
#15 0x30217416 in __CFNotificationCenterDarwinCallBack ()
#16 0x3020d0b0 in __CFMachPortPerform ()
#17 0x30254a76 in CFRunLoopRunSpecific ()
#18 0x3025416a in CFRunLoopRunInMode ()
#19 0x320452a4 in GSEventRunModal ()
#20 0x308f037c in -[UIApplication _run] ()
#21 0x308eea94 in UIApplicationMain ()
#22 0x00002096 in main (argc=1, argv=0x2ffff514)

Currently I have a very weird error in my program. Sometimes it happens, and sometimes, it doesn't. But here's a summary of what's going on:

When the program starts up:

  • saved data (just a short plist consists of 13 elements) is loaded if it exists.
  • a huge plist containing 1014 strings is loaded into NSMutableDictionary.
  • another plist containing 78 strings is loaded into an NSArray.
  • a .mp4 movie is played.

The error occurs at a part where OpenGL ES View is being removed and the user is about to view one of the strings of the 1014 strings in the NSMutableDictionary.

This error never occur in the simulator. It only occur on the iPhone, and sometimes it runs fine but sometimes it crushes.

However, after reading the stacktrace, I see CFDictionaryApplyFunction in there, so I thought it might be one of the possible causes. Is it because on the simulator, it reads things so fast that the whole dictionary from the plist is loaded at an instant, while on the device, it reads slower? Honestly, I do not know exactly how the dictionary works. Does it read through all 1014 strings at an instant, or it uses some other threads to read slowly? Please advice. Thank you.

+5  A: 

When you get an EXC_BAD_ACCESS, it often means you're trying to call a method on an object that isn't there -- probably because it's been deallocated.

About halfway down the trace, there are some memory warning calls, such as:

#12 0x30a00710 in -[UIApplication _performMemoryWarning] ()

Which makes it appear that none of your code is directly causing the crash, but rather a system notification when memory runs low.

Closer to frame #0, it appears to be attempting to clear the cache of a UIImage object, and this appears to be the bad access.

Based on this, one guess is that you're assigning a pointer to the autoreleased return value of a convenience constructor; then the object is autoreleased, and you might think it's fine because you don't use the image directly, but the memory warning tries to access it. For example:

@interface MyClass {
  UIImage* myImage;
}
// ...
- (id) init {  /* the usual stuff */
  myImage = [UIImage imageNamed:@"bob_the.png"];
  return self;
}

In this example, even if you have a retain property set up on myImage, you're not actually retaining the image unless you set the value via self.myImage. So, shortly after this call, the image is released, and you've got a pointer to no man's land.

Without seeing the code, I have no way of knowing if that's what's actually going on, but it's one type of mistake that's easy to make.

These related questions give tips on similar crashes: EXC_BAD_ACCESS debugging question 1 and question 2.

Finally, if none of that helps, I suggest finding a minimal reproduction of your problem. The hard way to do this is to copy your code, cut out half, see if the error is still there, and repeat until you get the smallest code you can find which reproduces the error. It's usually a lot easier to debug from there (and more postable as a stackoverflow question, too!) If you know the easy way, let me know.

Tyler
You can also assign it like this: `myImage = [[UIImage imageNamed:@"bob_the.png"] retain]`.
notnoop
According to what you've said, maybe this part is the cause of the trouble? This code below is in the method of a subclass of UIImageView.NSString* st;st = [[NSString alloc] initWithFormat:@"sc%d.png", chosenNumber];self.image = [UIImage imageNamed:st];[st release];Basically I set an image of the UIImageView like that. Is it possible that this is the cause?
unknownthreat
Allow me to test it some more to see it does not cause any more error. Right now, I have a retained UIImage* in my UIImageView subclass. Thank you very much, Mr. Tyler. (bowing as a student)
unknownthreat
unknownthreat - if image in self.image is a retained property, then that code is ok (not buggy), since "self.image = X" implicitly calls retain for you. Check that you have "retain" after @property in the header file where you declare image as a member variable.Daniel Rinser (another answer here) has good advice explaining how to set up the NSZombiesEnabled variable to help get more debug info.
Tyler
I got a bad news. It seems that the error occured once again. But after I ran my app on the device from XCode, the error stop occuring. But I think the main problem is UIImage for sure.
unknownthreat
+1  A: 

You may want to set the NSZombiesEnabled environment variable. This way your app won't crash with EXC_BAD_ACCESS when accessing released objects, but rather logs an informative message to your console. This blog post explains pretty well what happens and how to set it up in XCode. Anyways, NEVER EVER forget to disable this option in production releases, since otherwise your objects will never be released!

Daniel Rinser