How EXC_BAD_ACCESS in objc_msgSend if receiver, parms OK?
How EXC_BAD_ACCESS in objc_msgSend if receiver, parms OK?
- Subject: How EXC_BAD_ACCESS in objc_msgSend if receiver, parms OK?
- From: Jerry Krinock <email@hidden>
- Date: Fri, 17 Feb 2012 08:53:15 -0800
I got an EXC_BAD_ACCESS in objc_msgSend. By probing registers in gdb, I am able to get the receiver, selector and the single parameter of the offending message.
(gdb) po *(int*)($ebp+8)
<BkmslfWinCon: 0xcdbf570>
(gdb) po NSStringFromSelector(*(int*)($ebp+12))
updateAgentActivityNow:
(gdb) po *(int*)($ebp+16)
<__NSCFTimer: 0x9315960>
So it's is a message from Cocoa's timer-firing mechanism, firing the selector of a timer. Given where the program was, this message is expected.
Both the receiver (a window controller) and the method's parameter (a timer) both seem to be good, live, valid objects…
(gdb) po 0xcdbf570
<BkmslfWinCon: 0xcdbf570>
(gdb) po [0xcdbf570 window]
<SSYHintableWindow: 0xcd8deb0>
(gdb) po 0x9315960
<__NSCFTimer: 0x9315960>
(gdb) po [0x9315960 userInfo]
{
agentLabel = "6609802C6B47.000.001.doSoon.36665";
}
I "manually" sent most of the messages in the offending method, and got mostly expected results [1]. One message was too hairy to send manually.
So how could there have been EXC_BAD_ACCESS? In my experience, I think that I've seen such inexplicable crashes caused by something *really* bad in the offending method, such as wrong parameters in a format string. I think that sometimes gdb gets so upset that it can't show you the top of the call stack. Is that true?
If I try to manually send the crashed message using gdb's 'call' command, I also get EXC_BAD_ACCESS…
(gdb) call [0xcdbf570 updateAgentActivityNow:0x9315960]
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x63610002
0x9985cd4b in objc_msgSend ()
The program being debugged was signaled while in a function called from GDB.
GDB remains in the frame where the signal was received.
To change this behavior use "set unwindonsignal on"
Evaluation of the expression containing the function (objc_msgSend) will be abandoned.
What could be going on here?
The crash occurs on the main thread.
I would like to discount this crash as an artifact of my using Xcode 3 under Mac OS 10.7, but unfortunately the offending method is one that I recently added to a large project. Not a likely coincidence.
Thanks,
Jerry Krinock
Here is the call stack:
#0 0x9985cd47 in objc_msgSend
#1 0x003053cc in maxInt.32934
#2 0x9b850bdf in __NSFireTimer
#3 0x92511656 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__
#4 0x92510fe7 in __CFRunLoopDoTimer
#5 0x924eff70 in __CFRunLoopRun
#6 0x924ef47c in CFRunLoopRunSpecific
#7 0x924ef328 in CFRunLoopRunInMode
#8 0x91e5617f in RunCurrentEventLoopInMode
#9 0x91e5d4e7 in ReceiveNextEventCommon
#10 0x91e5d356 in BlockUntilNextEventMatchingListInMode
#11 0x9bb07a9c in _DPSNextEvent
#12 0x9bb07306 in -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:]
#13 0x9bb03675 in -[NSApplication run]
#14 0x9bd97261 in NSApplicationMain
#15 0x00001e15 in main at MainApp-Main.m:49
[1] Here is the offending method, with comments added to show the results of my "manually" running the lines.
- (void)updateAgentActivityNow:(NSTimer*)timer {
// I have subclassed NSApp so I can switch off "dock bouncing". See below [2].
[NSApp setBeQuiet:YES] ;
// When I tried to send the above message manually, I got an inexplicable result:
// (gdb) call [NSApp setBeQuiet:1]
// Value can't be converted to integer.
// I don't know what that means.
Bkmslf* bkmslf = (Bkmslf*)[self document] ;
// Sending the above message "manually" returns the live document as expected.
BkmxAgentActivity oldState = [self agentActivityFilteredState] ;
BkmxAgentActivity newState = [self agentActivityLastInputState] ;
[self setAgentActivityFilteredState:newState] ;
// Sending the above three messages manually works OK.
// I can even set and then get those two attributes.
if (oldState != BkmxAgentActivityNone) {
// Based on value of old state, this branch would have executed.
[self dismissAgentActivityAlertSheet] ;
// However I don't think there's any problem here. See below [3].
}
NSString* irregularAgentLabel = [[timer userInfo] objectForKey:constKeyAgent] ;
// Sending the above message manually gives the expected result
if (newState == BkmxAgentActivityStaged) {
// Based on value of newState, this branch *would* be executed.
if ([self shouldPerformNow]) {
// Based on value of shouldPerformNow, this branch *would* be executed.
Agent* agent ;
Trigger* trigger ;
// I didn't try to send this message since I don't know the values
// of the two return-by-reference parameters.
[self whyForAgentLabel:irregularAgentLabel
agent_p:&agent
trigger_p:&trigger] ;
// So then, I couldn't try this either…
[agent dropAndDoTrigger:trigger] ;
}
else {
// Omitted code for branch which would not have executed
…
}
}
else if (newState == BkmxAgentActivityWorking) {
// Omitted code for branch which would not have executed
…
}
[NSApp setBeQuiet:NO] ;
}
[2] Subclass of NSApp to control dock bouncing. I don't think there's any problem here.
@interface QuietableApp : NSApplication {
BOOL m_beQuiet ;
}
@property (assign) BOOL beQuiet ;
@end
@implementation QuietableApp
@synthesize beQuiet = m_beQuiet ;
- (NSInteger)requestUserAttention:(NSRequestUserAttentionType)requestType {
NSInteger identifier ;
if ([self beQuiet]) {
// Super always returns 0. So I do the same.
identifier = 0 ;
}
else {
identifier = [super requestUserAttention:requestType] ;
}
return identifier ;
}
@end
[3] I don't see any problem here either. Because agentActivityAlert
is nil, this would have been a no-op…
- (void)dismissAgentActivityAlertSheet {
[[self agentActivityAlert] setAlertReturn:NSAlertOtherReturn] ;
[[self agentActivityAlert] goAway] ;
[self setAgentActivityAlert:nil] ;
}
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden