这是前一篇文章 https://blog.csdn.net/LGYXDN/article/details/118215454 的超集。

  • macOS上进程崩溃时生成dump文件

    • 首先确保 /cores 目录存在,并且有相应权限
    • 进程开启写dump
  • 内存问题
    • sanitizer

      • 工程配置中会涉及到场景
    • malloc特性
    • 使用开源的 Valgrind
  • 参考

macOS上进程崩溃时生成dump文件

macOS系统上,程序发生崩溃的时候,默认会生成一个.crash文件。如果想要更多的进程active信息,我们需要core dump。

默认macOS系统有一个目录 /cores,但是需要app开启dump功能,才会在这个目录下生成对应的core dump文件。

方法如下:

首先确保 /cores 目录存在,并且有相应权限

ref:Core Dumps,有些信息过期了,比如现在10.15.6上面没有 /etc/launchd.conf 文件。

保证系统中存在 /cores 目录
$ sudo mkdir /cores /cores 设置必要的属性
$ sudo chown root:admin /cores
$ sudo chmod 1775 /cores
$ sudo chmod o+w /cores/cores 默认的属性是:
$ l /cores
total 0
drwxr-xr-x   2 root  wheel    64B 12 14  2019 .
drwxr-xr-x  20 root  wheel   640B  1  1  2020 ../cores 经过上面的设置之后是:
$ l /cores
total 0
drwxrwxrwt   4 root  admin   128B Jul 11 18:06 .
drwxr-xr-x  23 root  wheel   736B Aug 22  2020 ..

到底上面这个wheel是什么,参考 What is the "wheel" user in OS X?

还需要确认下:

同时,还需要查看系统是否开启core dump功能。
$ sudo sysctl kern.coredump=1
也可以先通过命令查看:
$ sysctl kern.coredump
输出为1表示开启,输出为0表示未开启。
不过我发现目前这个默认是开启的。

进程开启写dump

通过命令行设置系统层面的core dump文件大小,先查看目前的设置:
$ ulimit -c
如果输出是0,那么表示没有开启core dump。设置不限大小的方法是:
$ ulimit -c unlimited
再次使用 ulimit -c 查看将会输出unlimited。但是目前这个设置,在我的系统上macOS 10.15.6上好像不起作用了。需要像下面这样在需要开启的进程中通过调用系统接口设置开启/关闭。

ref: [Resolved] App crashes when launched from dock, doesn't crash when run from terminal

实验有效的方法是:

struct rlimit limit;
BOOL success = getrlimit(RLIMIT_CORE, &limit) >= 0;
assert(success);
limit.rlim_cur = limit.rlim_max;
success = setrlimit(RLIMIT_CORE, &limit) >= 0;
assert(success);

不过 Mac OS X Debugging Magic 中给的写法是:

#include <sys/resource.h>static bool EnableCoreDumps(void)
{struct rlimit   limit;limit.rlim_cur = RLIM_INFINITY;limit.rlim_max = RLIM_INFINITY;return setrlimit(RLIMIT_CORE, &limit) == 0;
}

通过上面的设置之后,如果macOS系统中的进程发生崩溃,会有core dump文件在 /cores 目录下生成。然后就可以通过lldb,gdb等工具调试了。下面是出现dump时,/cores目录下文件结构。

➜  ~ l /cores
total 18651416
drwxrwxrwt   4 root  admin   128B Jul 11 18:06 .
drwxr-xr-x  23 root  wheel   736B Aug 22  2020 ..
-r--------@  1 will  admin   4.3G Jul 11 18:00 core.46972
-r--------@  1 will  admin   4.6G Jul 11 18:06 core.47125

不过有一个问题,一旦支持生成core dump的话,在console中刷新到生成crash文件似乎要延迟较久的时间,我电脑上大约是5分钟,比如crash文件实际创建的时间是 2021-07-11 18:06:23.162 +0800,但是console中列出的时间是 2021/07/11, 18:11 。

内存问题

macOS上有两个现成的工具:sanitizer和malloc特性

sanitizer

AddressSanitizer是一项编译和运行时技术,用于发现难以定位的bug。作用于编译选项,是编译器支持的。因为这也是一项运行期技术,所以对于一些第三方的二进制库,也可以定位其存在的内存问题。

Google官方文档参考:AddressSanitizer,要认真阅读这篇文档,比如里面提到FORTIFY_SOURCE与asan/msan/tsan不能一起使用,gcc,clang编译出来的代码不要混合asan一起使用,asan默认填充申请出来的内存值为0xbe等等,还有想要一次性打印所有检测到的问题,而不是碰到一个就停下来,可以 -fsanitize-recover=address 配合环境变量 ASAN_OPTIONS=halt_on_error=0来实现。

webrtc的源码中 src/build/config/compiler/BUILD.gn 有一段代码:

if (!is_debug && !using_sanitizer &&(!is_linux || !is_clang || is_official_build) &&current_cpu != "s390x" && current_cpu != "s390" &&current_cpu != "ppc64" && current_cpu != "ppc64" &&current_cpu != "mips" && current_cpu != "mips64") {# _FORTIFY_SOURCE isn't really supported by Clang now, see# http://llvm.org/bugs/show_bug.cgi?id=16821.# It seems to work fine with Ubuntu 12 headers though, so use it in# official builds.## Non-chromium code is not guaranteed to compile cleanly with# _FORTIFY_SOURCE. Also, fortified build may fail when optimizations are# disabled, so only do that for Release build.defines += [ "_FORTIFY_SOURCE=2" ]
}

可以看出,sanitizer与_FORTIFY_SOURCE不同时使用

sanitizer的详细参数控制参考:AddressSanitizerFlags。

macOS 系统上,对于没有启用沙盒的app,使用sanitizer需要安装llvm-symbolizer使得生成的报告中提供更详细的信息,否则生成的错误报告中不会报告正确的代码行数,而是一个内存地址。也就是这里描述的问题:Symbolizing the Reports

禁止链接的第三方二进制库文件的错误报告、禁止某些函数和源文件的错误报告、忽略某些文件的错误报告,可参考llvm的文档:Issue Suppression。这里提到macOS上如果开启了沙盒就无法实时(on-line)显示错误的代码行数,只能通过离线的方式(off-line)来翻译,使用的工具是dsymutil。不过实际使用下来看,如果是使用Xcode调试的话,基本也就不需要行数的提示了,调试器会自动在出问题的地方停下来。所以这个问题也就不需要解决了(除非是想要脚本化检测过程)。于是乎,可以直接在Xcode的scheme->Arguments->Environments Variables中添加环境变量:name填ASAN_OPTIONS,value填symbolize=0来关闭符号翻译。如果想设置其他选项,可以通过:连接。比如 detect_container_overflow=0:symbolize=0:halt_on_error=0

结合文档 Turning off instrumentation 可以了解到设置黑名单的方法是添加clang编译选项:-fsanitize-blacklist=my_ignores.txt,my_ignores.txt的格式是:

# Suppress error reports for code in a file or in a function:
src:bad_file.cpp
# Ignore all functions with names containing MyFooBar:
fun:*MyFooBar*
# Disable out-of-bound checks for global:
global:bad_array
# Disable out-of-bound checks for global instances of a given class ...
type:Namespace::BadClassName
# ... or a given struct. Use wildcard to deal with anonymous namespace.
type:Namespace2::*::BadStructName
# Disable initialization-order checks for globals:
global:bad_init_global=init
type:*BadInitClassSubstring*=init
src:bad/init/files/*=init

引用自 Suppressing Errors in Recompiled Code (Ignorelist)

webrtc中的示例代码位于: src/tools/memory/tsan_v2/ignores.txt

开启的方法可以分为两类:通过Xcode中的scheme,或者通过command line设置编译参数。具体参考 Diagnosing Memory, Thread, and Crash Issues Early

webrtc工程中子工程太多,需要通过gn来设置参数。在Mac上编译webrtc并开启内存清洗器的方法是在gn gen xxx的时候,在参数中添加上一句:is_asan=true,比如:

gn gen out/72 --ide="xcode" --args='target_cpu="x64" is_debug=false is_component_build=false mac_deployment_target="10.11" rtc_use_h264=true rtc_enable_protobuf=true ffmpeg_branding="Chrome"  is_asan=true'

其余的gn的编译选项中还有很多,但是macOS基本都用不了,比如:

  • 使用 is_ubsan_null,is_ubsan_vptr,is_ubsan_no_recover,use_cfi_diag的话,clang会有编译崩溃
  • is_msan 只支持Linux
  • is_safestack 不被clang (8.0.0)支持

sanitizer生成报告的各类错误对应的示例代码,可以参考微软的文档:AddressSanitizer error examples。Apple的文档在 Diagnosing Memory, Thread, and Crash Issues Early 下面的 Topic Address Sanitizer 小结中。推荐阅读微软的文档!!!

使用sanitizer之后,官方文档说是性能下降2倍,算是十分高效的了。

关于错误报告中的shadow bytes的概念,参考微软文档:AddressSanitizer shadow bytes,核心概念是1个影子字节映射8个虚拟内存字节。计算方式:

// x86
char shadow_byte_value = *((Your_Address >> 3) + 0x30000000)
// x64
char shadow_byte_value = *((Your_Address >> 3) + _asan_runtime_assigned_offset)

工程配置中会涉及到场景

  • 直接对clang设置asan参数的方法:
// ref: https://clang.llvm.org/docs/AddressSanitizer.html#usage
clang++ -O1 -g -fsanitize=address -fno-omit-frame-pointer example_UseAfterFree.cc
  • CMakeList.txt中控制cmake启用asan的方法:
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address")
  • CMakeList中配置生成的Xcode工程启用asan的方法:
set(CMAKE_XCODE_GENERATE_SCHEME ON)
set(CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER ON)
set(CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN ON)

malloc特性

这个是利用macOS系统上的malloc库支持的特性。参考 Malloc Debug Environment Variables Release Notes 和 Enabling the Malloc Debugging Features

不过有一点需要说明,malloc特性开启之后,app的性能下降非常多,这一点比sanitizer差很多。

使用开源的 Valgrind

macOS上支持的一直不太好,目前最新版本仅仅是初步支持macOS 10.13,ref:Valgrind Distribution Documents。如果使用home-brew来安装Valgrind的话,会报错:

valgrind: Linux is required for this software.
Error: An unsatisfied requirement failed this build.

可以尝试自行编译,参考 Valgrind on macOS Sierra,成功的可能性不太大。

valgrind -v your-program

参考

  • How to macOS Core Dump,How to generate core dump files,Managing Core Dumps
  • Mac OS 产生 Coredump,定位 Segmentation Fault
  • 10.15.5 & 10.15.4 = Wake from Sleep Kernel Panic on 16″ MBPro (2019)
  • Technical Note TN2118 Kernel Core Dumps 介绍了关于固件(firmware)变量 boot-args 的修改。
  • wwdc视频:Advanced Debugging and the Address Sanitizer 其中有提到malloc特性和sanitizer检测崩溃的原理
  • Xcode上通过cmake来控制scheme的设置:XCODE_GENERATE_SCHEME
  • Collecting Crash Reports, Mini-Dumps And Core Dumps中的MAC OS X部分,查看其脚本会发现,也是使用了开启core dump,然后通过脚本找到对应的pid,然后一旦发现/cores目录下有core.$pid之后就压缩好等用户上传。
  • [Resolved] App crashes when launched from dock, doesn't crash when run from terminal 附上一个不错的core dump分析过程。
  • How to get a core dump for a segfault on Linux 有关于 sysctl 的更多设置。
  • 定位多线程内存越界问题实践总结 2013年的文章,思路可以参考,工具有些无法使用了。
  • “Electric Fence: Who Let the Heap Corruption Out?”,Electric Fence,
  • llvm-symbolizer - convert addresses into source code locations
  • Security Technologies: FORTIFY_SOURCE,Toward _FORTIFY_SOURCE parity between Clang and GCC

macOS上如何应对崩溃问题相关推荐

  1. tess4j识别中文在linux,macOS上运行tess4j识别中文报错问题

    最近在做一个项目时,需要用到OCR识别技术,而且要求识别世界上大多数的常用语言,也要考虑一些小语种的识别.之前对这个领域比较默生,经过一番研究,发现目前比较成熟的能够识别多语言的OCR主要是有道和百度 ...

  2. 在macos上基于python2.7安装PyQt5

    在macos上基于python2.7安装PyQt5 在python3上面安装PyQt5是十分简单的,可是,在python2.7上安装这个东西,着实让人折腾了一把.要总结一下,年纪大了,记性不好. 首先 ...

  3. windows 10 上office2016 word崩溃的解决方案

    windows 10 上office2016 word崩溃的解决方案 参考文章: (1)windows 10 上office2016 word崩溃的解决方案 (2)https://www.cnblog ...

  4. 如何在iOS或macOS上检查活动的Internet连接?

    我想检查一下我是否在使用Cocoa Touch库的iOS上或在使用Cocoa库的macOS上建立了Internet连接. 我想出了一种使用NSURL做到这一点的方法. 我这样做的方式似乎有点不可靠(因 ...

  5. qtiplot编译失败linux,在macOS上安装 qtiplot 免费版

    8种机械键盘轴体对比 本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选? 最近更新时间:2019-10-04 一.简介 众所周知,对于广大科研狗来说,origin是一款不可多得的使用软件,但or ...

  6. macos自带java_在 MacOS 上安装 Java - Java 入门教程

    本小节我们将介绍如何在 MacOS 平台安装 Java . 如果你想在其他平台安装 Java,请查看对应平台的安装教程: 1. 下载安装包 我们首先打开 Oracle 官网的 JDK 下载地址,找到 ...

  7. macOS上实现Qt应用程序做文件关联打开

    一.背景介绍 用Qt开发的应用程序要实现文件关联,双击时用默认关联的程序打开文件,在Windows上这个功能非常容易实现.Windows应用程序在安装的时候可以在注册表中写入相关的键值对.打开文件的时 ...

  8. macos 全局快捷键 打开 iterm_在 macOS 上实用的十大软件!你get了吗?

    在 macOS 里面有什么实用的软件?在这里分享一下我在我的 MacBook Pro上日常使用特别多的软件. MacBook型号:MacBook Pro 2018 款 15 英寸 系统版本:macOS ...

  9. android 内存播放视频播放器,视频流媒体播放器EasyPlayer-RTSP安卓版在RK3399上运行APP崩溃问题...

    原标题:视频流媒体播放器EasyPlayer-RTSP安卓版在RK3399上运行APP崩溃问题 我们的流媒体服务器现在都已经支持H.265编码视频的播放,流媒体播放器EasyPlayer就是目前比较稳 ...

最新文章

  1. linux 找不到动态链接库 .so文件的解决方法
  2. 2019.01.19-2018年6月NEYC集训counting
  3. 云原生生态周报 Vol. 13 | Forrester 发布企业级容器平台报告
  4. 贪吃蛇程序不要白不要,一个赞就够了
  5. Pycharm如何导入python包
  6. mysql xa 使用_MySQL如何实现 XA 规范
  7. 不同版本的nutz与log4j2的集成方法
  8. 你不能访问此共享文件夹,因为你组织的安全策略阻止未经身份验证的来宾访问
  9. windows安装MobaXterm
  10. PLSQL 安装教程
  11. json格式的字符数据转换成map格式
  12. 【智慧楼宇项目】nodemcu(lua)控制HLW8032电计量模块
  13. 遍地是钱,为什么捡不到?
  14. HTML,CSS,JavaScript知识树思维导图
  15. UIDataCollector的下载和使用
  16. SpringBoot笔记(五)Linux系统与项目部署
  17. html id命名规范,关于Html class id 命名规范
  18. 谈小学计算机教学,浅谈小学计算机教学方法
  19. 超五类网线与六类网线水晶头为什么不可通用
  20. python鸭子类型_1

热门文章

  1. vuex是什么 以及他的优缺点
  2. [usOJ6276]和平共处
  3. fiddle导出jmx文件_Fiddler导出JMX文件配置
  4. 正则匹配表达式语法(二)
  5. python 画函数曲线
  6. markdown进阶语法-设置换行,文本对齐方式等
  7. 计算机课玩手机检讨500,教室上课玩手机检讨书500字
  8. Nice!JavaScript基础语法知识都在这儿了
  9. 程序人生 - Python爬虫要违法了吗?告诉大家:守住规则,大胆去爬
  10. 电子邮箱地址注册,收费邮箱哪个安全?申请163电子邮箱?