0

我在分发构建中符号化一些代码时遇到了麻烦,最后创建了一个简单的项目,该项目有一个按钮,通过访问不存在的数组中的 objectAtIndex 基本上会导致崩溃。

在发布(或分发)构建中,当 MyApp 函数调用完全丢失时,跟踪会像这样出现:

0- CoreFoundation                   0x34dcb29e __exceptionPreprocess + 158
1   libobjc.A.dylib                 0x3537397a objc_exception_throw +26 
2   CoreFoundation                  0x34d16b70 -[__NSArrayM objectAtIndex:] + 160 
3   UIKit                           0x311a40a0 -[UIApplication endAction:to:from:forEvent:] + 68
4   UIKit                           0x311a4052 -[UIApplication sendAction:toTarget:fromSender:forEvent:]   + 26 
5   UIKit                           0x311a4030 -[UIControl sendAction:to:forEvent:] + 40     
6   UIKit                           0x311a38e6 -[UIControl(Internal) _sendActionsForEvents:withEvent:] +   498
...

在调试构建中,它显示了 MyApp 函数,其中导致崩溃的代码是:

0   CoreFoundation                  0x34dcb29e __exceptionPreprocess + 158
1   libobjc.A.dylib                 0x3537397a objc_exception_throw + 26
2   CoreFoundation                  0x34d16b70 -[__NSArrayM objectAtIndex:] + 160
3   MyApp                           0x00098128 -[ViewController processArray] (ViewController.m:58)
4   MyApp                           0x0009814e -[ViewController Crash:](ViewController.m:63)**
5   UIKit                           0x311a40a0 -[UIApplication sendAction:to:from:forEvent:] + 68
6   UIKit                           0x311a4052 -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 26
7   UIKit                           0x311a4030 -[UIControl sendAction:to:forEvent:] + 40
8   UIKit                           0x311a38e6 -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 498

在执行相同的部署测试并单击按钮后,上述痕迹不在设备日志中。

关于 SO 的几篇文章/博客/问题已经讨论了符号问题,其中显示了十六进制符号而不是方法名称等(这与这个问题不同),我尝试从派生数据中删除东西,清理构建目录等但是这个可以持续复制。谁能解释一下为什么会这样。

编辑:添加代码以便于参考:

-(void) processArray
{
    NSMutableArray *array = [NSMutableArray arrayWithObjects:@"One", @"Two", @"Three", nil];
    [array objectAtIndex:3];//Intentional crash for testing
}

- (IBAction)Crash:(id)sender 
{    
    [self processArray];
}
4

1 回答 1

0

尝试关闭编译器优化并在发布版本中重现崩溃。

我怀疑您被尾调用优化所困扰。编译器可能会直接从方法的末尾向任何调用的方法发出 JMP 指令。

即在这种情况下:

 - (void)boo
 {
    [self bangAGong];
 }

由于没有返回值等......编译器可以重写调用以bangAGong使其重用当前堆栈帧。这称为尾调用(也是objc_msgSend()工作原理。通过这样做,它消除了返回时的帧弹出。

这使您的代码运行得稍微快一些,但也意味着它看起来像是从崩溃报告中删除了堆栈帧。

于 2013-06-06T20:11:10.093 回答