Help tracking down “EXC_BAD_ACCESS”

Yeah, it's kind of a generic problem.

I have an iPhone 3.0 Utility App template that I was adding fields to the FlipsideViewController nib/h/m files which somehow got stuck with an error telling me it could not find a definition for protocol FlipsideViewControllerDelegate. I finally gave up after commenting out nearly the entire module.

I then copied in new FlipsideViewController.h/.m files and cut and pasted in all my earlier changes and verified that all the same connections were present as in a blank Utility App, and my additional IBOutlet and IBActions.

Now, when I click on the (Done) button, I get the “EXC BADACCESS”.

Tracing in gdb, with breakpoints shows it completes
- (IBAction)done {
[self.delegate flipsideViewControllerDidFinish:self];
}
in FlipsideViewController.m, which includes
- (void)flipsideViewControllerDidFinish:(FlipsideViewController *)controller {
// removed 3.0 line to use flip, so can build with 2.2.1 base SDK
[self dismissModalViewControllerAnimated:YES];
}

and not sure where to put the next breakpoint, it does the transition, then gets the exception.
So my screen shows the MainView window as expected.

All of this WAS working fine, before I added the additional IBOutlet/IBAction and had the protocol issue. It's possible an IBOutlet/Action is setup wrong, or dropped, but those usually show up with the wrong datatype sent to an instance. In this case, I just get the “EXC BADACCESS”. The stack backtrace is not really helpful in identifying where else to look.
(gdb) bt
#0 0x90a1a68c in objc_msgSend ()
#1 0x00005b96 in -[Scenes dealloc] (self=0x529eb0, _cmd=0x90a5b514) at /Volumes/Olorin/Projects/Pusher/Scenes.m:83
#2 0x00004046 in -[MainView dealloc] (self=0x525b00, _cmd=0x90a5b514) at /Volumes/Olorin/Projects/Pusher/Classes/MainView.m:229
#3 0x922bc38a in CFRelease ()
#4 0x92289709 in __CFDictionaryDeallocate ()
#5 0x922bc538 in _CFRelease ()
#6 0x91725f6f in __delayedPerformCleanup ()
#7 0x922b96db in CFRunLoopTimerInvalidate ()
#8 0x922ba629 in CFRunLoopRunSpecific ()
#9 0x922baaa8 in CFRunLoopRunInMode ()
#10 0x31566600 in GSEventRunModal ()
#11 0x315666c5 in GSEventRun ()
#12 0x30a4eca0 in -[UIApplication _run] ()
#13 0x30a5a09c in UIApplicationMain ()
#14 0x00002c28 in main (argc=1, argv=0xbfffef08) at /Volumes/Olorin/Projects/Pusher/main.m:14


Any pointers will be appreciated.

PB Ti G4 1Gh 10.5.7 768M, 15" iMac G4 800Mh 10.3.9 768M DM9 1.6Gh 10.5.7 2G, Mac OS X (10.5.7), PM8600/300Mhz MacOS 9.0 513M, PM8500/132/405Mhz 10.1 Server, Centris 650, Quadra

Posted on Sep 19, 2009 2:41 PM

Reply
16 replies

Sep 19, 2009 5:33 PM in response to reststop

reststop wrote:
The stack backtrace is not really helpful in identifying where else to look. {code}(gdb) bt
#0 0x90a1a68c in objc_msgSend ()
#1 0x00005b96 in -[Scenes dealloc] (self=0x529eb0, _cmd=0x90a5b514) at /Volumes/Olorin/Projects/Pusher/Scenes.m:83


That seems fairly helpful. I'd guess you're trying to use an object that's already been destroyed in your dealloc method around line 83.

Sep 19, 2009 7:32 PM in response to reststop

(gdb) bt
#0 0x90a1a68c in objc_msgSend ()
#1 0x00005b96 in -[Scenes dealloc] (self=0x529eb0, _cmd=0x90a5b514) at /Volumes/Olorin/Projects/Pusher/Scenes.m:83
// You are releasing an object that is already deallocated.
#2 0x00004046 in -[MainView dealloc] (self=0x525b00, _cmd=0x90a5b514) at /Volumes/Olorin/Projects/Pusher/Classes/MainView.m:229
// That object is being held by the MainView, which is being deallocated
#3 0x922bc38a in CFRelease ()
#4 0x92289709 in __CFDictionaryDeallocate ()
// The MainView is in a dictionary somewhere that is being deallocated
#5 0x922bc538 in _CFRelease ()
#6 0x91725f6f in __delayedPerformCleanup ()
#7 0x922b96db in CFRunLoopTimerInvalidate ()
// Because a timer is being invalidated
#8 0x922ba629 in CFRunLoopRunSpecific ()
#9 0x922baaa8 in CFRunLoopRunInMode ()
#10 0x31566600 in GSEventRunModal ()
#11 0x315666c5 in GSEventRun ()
#12 0x30a4eca0 in -[UIApplication _run] ()
#13 0x30a5a09c in UIApplicationMain ()
#14 0x00002c28 in main (argc=1, argv=0xbfffef08) at /Volumes/Olorin/Projects/Pusher/main.m:14


So, a timer is being invalidated. That timer has a pointer to MainView, which has a pointer to Scenes. Normally, this should be no big deal. You are dying because, by the time the timer is invalided, Scenes is long gone. This shouldn't happen. Once you give MainView to the timer, it should retain it. The Scenes pointer in MainView also should be retained. If, during this invalidation, those were the last retains, Scenes should be deallocated with no problem.

Take a look at "Timer Programming Topics for Cocoa". Your target's timer may be trying to invalidate the timer during the target's deallocate. You normally don't need to keep track of a timer after scheduling it. Just let it go. Another possibility is that you've added a pointer to Scene to MainView without retaining it and have already deleted Scenes elsewhere. Without seeing the case, I can't say for sure.

Sep 19, 2009 9:37 PM in response to reststop

Notice that the app was built using the 3.0 SDK templates.
It seems that the error occurs when I rebuilt it, as is for 2.2.1 SDK as the base.
When built wiht the base set to 3.0, the error does not occur.

I suspect the problem lies in some difference in the templates, but have no
proof of this at present. I was setting self.delegate to nil in viewDidUnload as
cleanup, but am not sure it is necessary.

The stack hints at maybe a problem in releasing a pointer to my scene object
but that should only be released if the MainView object is released, unless I
have an alloc/release mismatch releasing too many times. That will be my
next check.

Sep 19, 2009 9:48 PM in response to etresoft

Thank you etresoft for the info. My stack tracing isn't so hot yet with Xcode/gdb/objective-C.
I'm just starting to get the hang of it. It's possible that it's caused by direct access to some
pointers, field=value; vs. self.field = value doing a retain. I will be doing a scour of my
entire project due to that.

If that clears it up, then your information is likely spot on.

Guess this happens when one is rushing to add the next phase without dotting the i's first.
I'm just so proud that I have all the game and reset logic working so quickly, that i may have
cut a few corners. It's time to download Clang and find out how to use it.

Then get back to work on changing user defaults and config info in-app, and figure out
how to best save current state so I can reload and continue from where the user left off.

Sep 20, 2009 7:36 AM in response to reststop

reststop wrote:
Guess this happens when one is rushing to add the next phase without dotting the i's first.
I'm just so proud that I have all the game and reset logic working so quickly, that i may have
cut a few corners. It's time to download Clang and find out how to use it.


Why? You're alone in rushing to the next phase. Xcode 3.2 is still pretty rough around the edges. I just submitted a bug against it where a 15-line Hello-World-type program produces incorrect output. And this is with the "stable" GCC 4.2 compiler. Plus, Clang doesn't support iPhone yet.

If you want to play around with it and can set it up in a purely test environment, then go for it. Otherwise, you may find yourself tracking down Apple's bugs as well as your own.

Sep 20, 2009 7:38 AM in response to reststop

reststop wrote:
The stack hints at maybe a problem in releasing a pointer to my scene object
but that should only be released if the MainView object is released, unless I
have an alloc/release mismatch releasing too many times. That will be my
next check.


According to your stack trace, that is exactly what is happening.

If you could setup an Xcode 3.2 test environment, it may be useful. I have heard that Xcode 3.2 includes a nice code analyzer that will help you track down memory errors exactly like this one.

Sep 20, 2009 8:52 AM in response to etresoft

I haven't finished my tidying up yet, but I agree with what you said about the stack trace. However, mainView is only ever deallocated when the game is completely finished, unless somehow there isn't enough memory and it needs to be deallocated while the flipsideView is displayed. The only timer events are the animations for the modal dialogues, which is exactly when the error is occurring.

By rushing, I meant to complete all the major aspects of my program, not rushing to bring up 10.6 or even to upgrade to XCode 3.2. Thanks again for explaining the stack trace. Now, looking at it, I don't know why I didn't see it, except I haven't done enough of them lately to be comfortable.

I'll post back to this thread when I've made progress. (and mark replies as answered as well).

Sep 20, 2009 10:20 AM in response to etresoft

Quick memory question on this... in several places I have code such as:

self.currentSceneKey = [myScenes.sceneKeys objectAtIndex:sceneIndex];
NSDictionary* myScene = [myScenes.scenes objectForKey:currentSceneKey];
if (myScene) {
self.currentSceneName = [myScene objectForKey:@"Name"];
self.currentSceneNumber = [myScene objectForKey:@"Number"];
self.currentSceneTableau = [myScene objectForKey:@"Tableau"];
}

Line 1, copying a string from a dictionary, using self.field accessor with retain, OK

Line 2, temporary dictionary so I can retrieve 3 strings in lines 4-6
Does line 2 need to be alloced and inited with objects, and then released?

Second case, I access data from a string, and I believe from what I read, the substring returned will be auroreleased and an extra retain may be put on the original string until the release, but this construct appears in context in several places, and I don't really know if I should be doing allocs and inits, or if that is overkill.

for (int i=0; i<boardWidth; i++) {
for (int j=0; j<boardHeight; j++) {
NSString* imgKey = [currentSceneTableau substringWithRange:NSMakeRange(((jboardWidth)+i)3,2)];
NSString* newKey = [myPieces.backgrounds objectForKey:imgKey]; // use board background
UIImage* img=[myPieces.figures objectForKey:newKey]; // get image
[img drawAtPoint:CGPointMake(i*cellSize, j*cellSize)];
}
}
imgKey is a 2 character NSString* as is newKey, each used jut to retrieve the correct image from the dictionary, which is then drawn. Is this OK, or is this a soruce of a memory leak?

I use the construct with the 2 NSString*s throughout my code and if these should be alloced/initted and then released, fine, I just need to know one way or the other. My current understanding is this is the right way to do it, as is coded, but I may be misinformed.

Sep 20, 2009 12:36 PM in response to reststop

reststop wrote:
mainView is only ever deallocated when the game is completely finished, unless somehow there isn't enough memory and it needs to be deallocated while the flipsideView is displayed.


Keep in mind that with Cocoa's retain/release mechanism, you really never have control of when memory is deallocated. All you do is retain/release. If you release an object whose retain count is zero, that object gets deallocated, whether you intended that to happen then or not.

The only timer events are the animations for the modal dialogues, which is exactly when the error is occurring.


When the timer gets invalidated, it releases its target and userInfo. In your case, it looks like your mainView's retain count has gotten to zero and it is getting deallocated.

I wouldn't worry too much about leaks until you get the crashing under control.

Sep 20, 2009 9:28 PM in response to etresoft

I don't have any explicit retain of MainView anywhere in my code. The object is initialized from Nib, and then added as a subview to my main window. There does not seem to be any problem when I build with SDK 3.0 as the base, but it now actually crashes rather than getting an EXC BADACCESS message. The backtrace now reads:

#0 0x90a1a688 in objc_msgSend ()
#1 0x922bc38a in CFRelease ()
#2 0x31dd1545 in CALayerUpdateSublayers ()
#3 0x31ddf43f in -[CALayer dealloc] ()
#4 0x31e126a7 in CALayerRelease ()
#5 0x31ddaf2b in CALayerFreeTransaction ()
#6 0x31dd260f in CATransactionCommit ()
#7 0x922b8772 in __CFRunLoopDoObservers ()
#8 0x922ba1d4 in CFRunLoopRunSpecific ()
#9 0x922baaa8 in CFRunLoopRunInMode ()
#10 0x31566600 in GSEventRunModal ()
#11 0x315666c5 in GSEventRun ()
#12 0x30a4eca0 in -[UIApplication _run] ()
#13 0x30a5a09c in UIApplicationMain ()
#14 0x00002950 in main (argc=1, argv=0xbfffef08) at /Volumes/Olorin/Projects/Pusher/main.m:14
For this particular crash, I started the app, and immediately selected the "i" to go to the flipside screen. The crash occurs when I select "Done" in the flipsideView. Subsequent tries give minor differences

objc[1210]: FREED(id): message release sent to freed object=0x54ceb0
#0 0x90a0abfa in objcerror ()
#1 0x90a0ac30 in _objcerror ()
#2 0x90a09637 in _freedHandler ()
#3 0x922bc38a in CFRelease ()
#4 0x31dd1545 in CALayerUpdateSublayers ()
#5 0x31ddf43f in -[CALayer dealloc] ()

It is consistent. It crashes in SDK 2.2 and 2.2.1, but runs (apparently) under SDK 2.0, 2.1 and 3.0 just fine, i.e. not crashing, and the modal dialog sets up and releases fine.

Any ideas. I added an explicit retain in both MainViewController and again in AppDelegate just after "creation" and those retains make no difference. My next best guess is it is some other object, not my main window, as first suspected/detected. I also disabled animation of the modal dialog.
So, I'm not really sure what the next thing to try is, except to double check the retain/release on other objects, starting with the flipside view.

I added NSLog messages at all the dealloc routines to see what is being deallocated, and the only output was from Flipside View (not flipsideViewController) and flipsideView doesn't release anything, although it does call
[super dealloc]

Sep 20, 2009 10:49 PM in response to etresoft

Ok, it seems that in FlipsideViewController either one or the other of

- (void)viewDidUnload {
// Release any retained subviews of the main view.
self.sceneLabel = nil;
self.sceneNameLabel = nil;
...
or

- (void)dealloc {
[sceneLabel release];
[sceneNameLabel release];
...
triggers the EXC BADACCESS exception. Not doing one or the other does not crash.

This bothers me, because this appears to be common in all the code examples I've seen. For any field defined as an object pointer, and which has RETAIN in it's property definition, the use of both

self.sceneLabel = nil;
and
[sceneLabel release];
is explicitly shown as the proper behavior. This is loaded from a Nib, as in most code examples as well. The ONLY other places in my code which access these locations is also in FlipsideViewController is

- (void)refreshFields {
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
MainViewController* mainViewController = (MainViewController*) delegate;
MainView* mainView = (MainView*) mainViewController.view;
sceneLabel.text = mainView.currentSceneKey;
sceneNameLabel.text = mainView.currentSceneName;
tileSetLabel.text = [[defaults objectForKey:@"tileSetName"] stringValue];
soundEffectsSwitch.on = ([[defaults objectForKey:@"soundEnabled"] isEqualToString:@"YES"]) ? YES : NO;
randomSceneSwitch.on = ([[defaults objectForKey:@"randomEnabled"] isEqualToString:@"YES"]) ? YES : NO;
}
which sets the proper values from the MainView or defaults instances. I did try this with both "field.text =" and "self.field.text" with no discernible difference. And in

- (void)viewWillDisappear:(BOOL)animated {
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
NSString* prefValue = (soundEffectsSwitch.on) ? @"YES" : @"NO";
[defaults setObject:prefValue forKey:@"soundEnabled"];
prefValue = (randomSceneSwitch.on) ? @"YES" : @"NO";
[defaults setObject:prefValue forKey:@"randomEnabled"];
[super viewWillDisappear:animated];
}
as you can see, there are all read references. Is there a bug in the 2.2.x runtimes since it doesn't crash with 2.1 or 3.0? (I didn't do an extensive trial of all the other SDK versions, since I only want to support the last free version and later).

I don't expect to add many more settings or defaults at this time, and I don't expect the user to constantly be flipping back and forth to change these.

Sep 21, 2009 1:23 AM in response to reststop

Well, apparently this is proper coding, or at least CLANG thinks so. My first runthrough, clang complained about my extra
[mainView retain];
as a memory leak, and also said to use

arc4random()
instead of
random()

and that was it. It apparently liked everything else. Cool. I was belaboring whether I was coding properly or not over nothing.

I still don't like commenting out one or the other of the "self.field=nil" or the "release", but if that stops me from crashing, It will have to do for now. I'd still like to know what might be different in 2.2 that causes the crash, but works fine in other versions.

This thread has been closed by the system or the community team. You may vote for any posts you find helpful, or search the Community for additional answers.

Help tracking down “EXC_BAD_ACCESS”

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple Account.