ios - backtrace 错过了导致崩溃的函数
问题描述
当我的应用程序崩溃时,我使用backtrace和backtrace_symbols来收集调用堆栈。
void InstallSignalHandler(void)
{
signal(SIGHUP, SignalExceptionHandler);
signal(SIGINT, SignalExceptionHandler);
signal(SIGQUIT, SignalExceptionHandler);
signal(SIGABRT, SignalExceptionHandler);
signal(SIGILL, SignalExceptionHandler);
signal(SIGSEGV, SignalExceptionHandler);
signal(SIGFPE, SignalExceptionHandler);
signal(SIGBUS, SignalExceptionHandler);
signal(SIGPIPE, SignalExceptionHandler);
}
void SignalExceptionHandler(int signal)
{
NSMutableString *mstr = [[NSMutableString alloc] init];
[mstr appendString:@"Stack:\n"];
void* callstack[128];
int i, frames = backtrace(callstack, 128);
char** strs = backtrace_symbols(callstack, frames);
for (i = 0; i <frames; ++i) {
[mstr appendFormat:@"%s\n", strs[i]];
}
NSLog(@"%@", mstr);
free(strs);
}
当我在控制台查看日志时,我发现日志错过了导致崩溃的函数。函数是:
+ (void)testCrash
{
int *nullPointer = NULL;
*nullPointer = 2019;
}
登录控制台是:
0 TestApp 0x0000000101d1e040 SignalExceptionHandler + 160
1 libsystem_platform.dylib 0x000000011002bb5d _sigtramp + 29
2 ??? 0x0000000000000000 0x0 + 0
3 TestApp 0x00000001019bbc6f __39+[MyCrashTesting showInViewController:]_block_invoke + 303
4 UIKit 0x000000010b09a559 -[UIAlertController _invokeHandlersForAction:] + 105
5 UIKit 0x000000010b09af5e __103-[UIAlertController _dismissAnimated:triggeringAction:triggeredByPopoverDimmingView:dismissCompletion:]_block_invoke.461 + 16
6 UIKit 0x000000010ae42ca2 -[UIPresentationController transitionDidFinish:] + 1346
7 UIKit 0x000000010ae46b12 __56-[UIPresentationController runTransitionForCurrentState]_block_invoke.436 + 183
8 UIKit 0x000000010ba2a3b4 -[_UIViewControllerTransitionContext c
我认为函数名称“testCrash”应该在日志的顶部。我做错了什么吗?
解决方案
由于这是一个非常简单的方法,没有参数并且在 clang 中没有 ARC 重载,Objective-C 编译器能够对删除消息运行时调用-O1
进行优化(足以实现这一点)。
您可以通过以下方式防止这种行为:
+ (void)testCrash __attribute__((optnone))
{
int *nullPointer = NULL;
*nullPointer = 2019;
}
这里学到的教训是,在程序执行期间,您永远不应该依赖特定的堆栈跟踪来实现某些目标。只要你理解了刚刚遇到的优化原理,诊断就可以了。
推荐阅读
- r - 基于跨多个列的多个可能的单元格可能性创建新列
- css - 我的页脚卡在页面中间
- json - 将 Json 文件内容保存到 python/pandas 中的 CSV 文件
- javascript - 无法使用 NodeJs 使用用户凭据登录
- javascript - 我应该如何在 onEvent 中放置两个 id?
- c# - 使用 inno.setup 创建 setup.exe 后拒绝访问目录和文件
- r - R中是否有一种方法,如果一列的值满足另一列中的某个标准,则该列的值应该是上面的值
- reactjs - 无法映射 React 中的查询
- ruby-on-rails - 在 Rails 上共享控制器操作/对象
- php - PHP我需要将逗号分隔的字符串拆分为一个数组,但是当逗号出现在数字之间时忽略它