正常程序运行出错,会被CrashRpt抓住,但是有时候没有抓住,程序就突然退出了,于是就发生了所谓的闪退。
哪些情况会闪退
| 项目 | 方式 | 说明 |
| 主动退出 | 调用exit 退出主循环 | 虽然不太可能,但是难免不会出现某个三方库包含了不干净的代码,埋藏了一个定时炸弹 |
| 主线程卡死 | 不响应系统事件 | 操作系统侦测到这种情况会主动杀死进程,进程没有机会捕捉异常并上报 |
| 未捕捉到异常 | 可能与运行的环境有关,具体原因需要进一步排查 | |
Windows Error Report(WER)
注册表配置项目
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\
HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\Windows Error Reporting\ (在 64位系统中运行 32 位程序)
| 配置项目 | 解释 | 默认值 |
| DebugApplications\ | ||
| [Application Name] | 是否调试 | 0 |
| LocalDumps\[Application Name]\ | 需要 LocalDumps 项目,否则不输出 dump | |
| DumpFolder | Dump输出路径 | %LOCALAPPDATA%\CrashDumps |
| DumpCount | Dump保存个数 | 10 |
| DumpType | Dump类型 | 0 - Custom dump |
| CustomDumpFlags | Dump Flags 前提:DumpType=0 | {MiniDumpWithDataSegs |MiniDumpWithUnloadedModules |MiniDumpWithProcessThreadData} |
参考:
收集User-Mode转储 - Win32 apps | Microsoft Docs
WER 设置 - Win32 apps | Microsoft Docs
闪退问题的应对措施
- 应用日志
查看闪退前的应用日志,日志中可能有一些蛛丝马迹,比如一些错误警告信息。通过日志也能够大概还原闪退前的使用操作,对分析与复现问题有很大帮助。
- 性能监控
应用闪退前的系统性能、应用性能对排查问题可能有一些帮助。建议测试前,配置Windows性能监控。参考:
Windows性能监控工具Perfmon的使用、性能指标分析
- 事件日志
在CrashRpt没有捕捉到异常时,Windows事件系统会记录到应用的这个错误,在一些情况下可以通过记录的信息来获取崩溃或问题位置。
- 闪退恢复
通过另一个进程辅助,重新启动应用,并上报闪退信息。
闪退上报方案
- Crashdump 收集
首先,需要添加下面这个注册表项,这样就能生成 crash dump 了,大部分机器一开始是没有的
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\
- 闪退监测
需要辅助进程来监测,与主进程一起启动,通过共享内存协助,主进程在共享内存中写入进程id,如果正常退出,就清空写入的信息(写入0)。
辅助进程监测到管道断开,并且共享内存中的pid没有清空时,就判断出主进程Crash了。
通过读取 Windows事件,进一步验证主进程Crash。如果 CrashRpt 抓住了应用异常,则没有相应的事件生成。这时候不需要上报闪退日志。
系统生成 Windows事件和 dump文件需要一段时间,这时候会有等待(不超过 5秒+10秒)。
- 日志上报
闪退日志上报与崩溃日志上报使用统一的后台接口。区别在于:
- 闪退日志没有截图
- zip包中没有截图、crashrpt.xml
- 应用重启
释放共享内存,重启主进程
附:CrashRpt原理
下面仅针对window平台的实现,说明一下异常捕捉(Catch)的原理,不包括上报方案。
CrashRpt: About Exceptions and Exception Handling
| 捕捉项目 | 系统API | 原理说明 | 备注 |
| 全局异常 | |||
| 结构化(SEH)异常 | SetUnhandledExceptionFilter | ||
| 虚函数调用异常 | _set_purecall_handler | _get_purecall_handler, _set_purecall_handler | Microsoft Docs | |
| 内存分配异常 | _set_new_mode _set_new_handler | ||
| 非法参数异常 | _set_invalid_parameter_handler | ||
| 非正常退出 | signal:SIGABRT | ||
| 中断信号 | signal:SIGINT | ||
| 终止信号 | signal:SIGTERM | ||
| 线程相关 | |||
| terminate调用 | set_terminate | ||
| unexpected调用 | set_unexpected | ||
| 浮点数异常 | signal:SIGFPE | ||
| 非法指令 | signal:SIGILL | ||
| 非法地址访问 | signal:SIGSEGV |
本文详细探讨了Windows应用程序闪退的各种原因,包括主动退出、主线程卡死、未捕获异常等,并介绍了WindowsErrorReport(WER)的注册表配置。此外,还提到了闪退的应对措施,如应用日志、性能监控和事件日志的分析,以及闪退恢复和Crashdump的收集。文章深入讲解了CrashRpt如何捕获和处理异常,涉及多种系统API和异常处理机制。
2万+

被折叠的 条评论
为什么被折叠?



