iPhone 6 上的 KERN_INVALID_ADDRESS 异常
Posted
技术标签:
【中文标题】iPhone 6 上的 KERN_INVALID_ADDRESS 异常【英文标题】:KERN_INVALID_ADDRESS exception on iPhone 6 【发布时间】:2015-08-19 20:15:28 【问题描述】:我们的ios
应用程序中抛出了一个KERN_INVALID_ADDRESS 异常。该应用程序实际上是一个Tamarin
应用程序,但异常发生在我们的PhoneGap
库中,该库基于PhoneGap
2.1 版的代码。该异常仅在iPhone 6
和iPad Air 2
设备上报告,而不在其他Apple
设备上报告。
这是符号化的崩溃报告:
Exception Type: EXC_BAD_ACCESS (SIGABRT)
Exception Subtype: KERN_INVALID_ADDRESS at 0x004c004900000072
Triggered by Thread: 0
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 libsystem_kernel.dylib 0x000000019853b270 0x198520000 + 111216
1 libsystem_pthread.dylib 0x00000001985d916c 0x1985d4000 + 20844
2 libsystem_c.dylib 0x00000001984b2b14 0x198450000 + 404244
3 Mobileforms 0x0000000100799384 mono_handle_native_sigsegv (mini-exceptions.c:2386)
4 Mobileforms 0x00000001007a61b0 mono_sigsegv_signal_handler (mini.c:6818)
5 libsystem_platform.dylib 0x00000001985d0958 0x1985cc000 + 18776
6 Mobileforms 0x0000000100155104 -[CDVConnection getConnectionInfo:] (CDVConnection.m:36)
7 Mobileforms 0x000000010014e948 -[NativeGapViewController execute:] (NativeGap.mm:205)
8 Mobileforms 0x000000010014e6d4 -[NativeGapViewController executeCommandsFromJson:] (NativeGap.mm:158)
9 Mobileforms 0x000000010014e58c -[NativeGapViewController flushCommandQueue] (NativeGap.mm:136)
10 Mobileforms 0x000000010014e2c4 -[NativeGapViewController handleRequest:] (NativeGap.mm:78)
在这里,我正在跟踪flushCommandQueue
方法中从第 136 行开始的代码。
NativeGap.mm: 136
/**
* Repeatedly fetches and executes the command queue until it is empty.
*/
- (void) flushCommandQueue
UIWebView* webView = (UIWebView*)self.view ;
[webView stringByEvaluatingjavascriptFromString:
@"cordova.commandQueueFlushing = true"];
// Keep executing the command queue until no commands get executed.
// This ensures that commands that are queued while executing other
// commands are executed as well.
int numExecutedCommands = 0;
do
// Grab all the queued commands from the JS side.
NSString* queuedCommandsJSON = [webView stringByEvaluatingJavaScriptFromString:
@"cordova.require('cordova/plugin/ios/nativecomm')()"];
numExecutedCommands = [self executeCommandsFromJson:queuedCommandsJSON]; // LINE 136
while (numExecutedCommands != 0);
[webView stringByEvaluatingJavaScriptFromString:
@"cordova.commandQueueFlushing = false"];
NativeGap.mm:158
/**
* Fetches the command queue and executes each command. It is possible that the
* queue will not be empty after this function has completed since the executed
* commands may have run callbacks which queued more commands.
*
* Returns the number of executed commands.
*/
- (int) executeCommandsFromJson:(NSString*)queuedCommandsJSON
// Parse the returned JSON array.
NSArray* queuedCommands = [queuedCommandsJSON cdvjk_mutableObjectFromJSONString];
// Iterate over and execute all of the commands.
for (NSArray* jsonEntry in queuedCommands)
CDVInvokedUrlCommand* command = [[CDVInvokedUrlCommand commandFromJson:jsonEntry] retain];
if(![self.commandDelegate execute:command]) // LINE 158
DLog(@"FAILED pluginJSON = %@", commandString);
[command release];
return [queuedCommands count];
NativeGap.mm: 205
- (BOOL) execute:(CDVInvokedUrlCommand*)command
...
// Find the proper selector to call.
NSString* methodName = [NSString stringWithFormat:@"%@:", command.methodName];
NSString* methodNameWithDict = [NSString stringWithFormat:@"%@:withDict:", command.methodName];
SEL normalSelector = NSSelectorFromString(methodName);
SEL legacySelector = NSSelectorFromString(methodNameWithDict);
// Test for the legacy selector first in case they both exist.
if ([obj respondsToSelector:legacySelector])
NSMutableArray* arguments = nil;
NSMutableDictionary* dict = nil;
[command legacyArguments:&arguments andDict:&dict];
//[obj performSelector:legacySelector withObject:arguments withObject:dict];
objc_msgSend(obj,legacySelector,arguments,dict);
else if ([obj respondsToSelector:normalSelector])
//[obj performSelector:normalSelector withObject:command];
objc_msgSend(obj,normalSelector,command); // LINE 205
else
// There's no method to call, so throw an error.
NSLog(@"ERROR: Method '%@' not defined in Plugin '%@'", methodName, command.className);
retVal = NO;
return retVal;
CSVConnection.m: 36
- (void) getConnectionInfo:(CDVInvokedUrlCommand*)command
CDVPluginResult* result = nil;
NSString* jsString = nil;
NSString* callbackId = command.callbackId; // LINE 36 << Exception
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:self.connectionType];
jsString = [result toSuccessCallbackString:callbackId];
[self writeJavascript:jsString];
在我看来,问题的根源在于方法executeCommandsFromJson
(NativeGap.mm: 158),特别是这段代码:
CDVInvokedUrlCommand* command = [[CDVInvokedUrlCommand commandFromJson:jsonEntry] retain];
if(![self.commandDelegate execute:command]) // LINE 158
DLog(@"FAILED pluginJSON = %@", commandString);
[command release];
在我看来,创建的这个 CDVInvokedUrlCommand
实例不知何故被提前释放,并且在到达 CSVConnection
中的这一行时已经被释放:
NSString* callbackId = command.callbackId; // LINE 36
这里是创建CDVInvokedUrlCommand
实例的相关部分:
+ (CDVInvokedUrlCommand*) commandFromJson:(NSArray*)jsonEntry
return [[[CDVInvokedUrlCommand alloc] initFromJson:jsonEntry] autorelease];
- (id) initFromJson:(NSArray*)jsonEntry
id tmp = [jsonEntry objectAtIndex:0];
NSString* callbackId = tmp == [NSNull null] ? nil : tmp;
NSString* className = [jsonEntry objectAtIndex:1];
NSString* methodName = [jsonEntry objectAtIndex:2];
NSMutableArray* arguments = [jsonEntry objectAtIndex:3];
return [self initWithArguments:arguments
callbackId:callbackId
className:className
methodName:methodName];
有谁知道为什么iPhone 6
会出现此异常以及我们如何解决它?
【问题讨论】:
【参考方案1】:如果它对其他人有帮助,这里是我花了几天时间寻找的这个问题的解决方案。崩溃仅发生在具有 64 位架构的设备上。 NativeGap.mm 中的这一行:
objc_msgSend(obj,normalSelector,command); // LINE 205
需要改成如下:
((void(*)(id, SEL, id))objc_msgSend)(obj,normalSelector,command); // LINE 205
关于这个问题的更多信息可以在over here找到。
【讨论】:
以上是关于iPhone 6 上的 KERN_INVALID_ADDRESS 异常的主要内容,如果未能解决你的问题,请参考以下文章
iPhone 3GS 上的 iOS 6.0 上的 UICollectionView 崩溃