分析崩溃报告
分析调试业务代码主要目的是追踪业务代码的问题,但有些问题是不会给我们追踪的机会的,比如那些偶发的、一旦出现应用程序就立即 Crash 的问题。要解决这些问题就要掌握分析 Electron 应用崩溃报告的知识。
如果你希望你的应用程序崩溃时,自动保存崩溃报告文件,那么你就要在你的应用程序中使用如下代码收集崩溃报告:
import { crashReporter } from "electron";
crashReporter.start({ submitURL: "", uploadToServer: false });
有了这段代码,当应用程序崩溃时,就会产生一个.dmp 扩展名结尾的文件(存放于 C://Users/[yourOsUserName]/AppData/Roaming/[yourAppName]/Crashpad)。
首先需要安装 WinDbg 调试工具,如果你在安装 Windows 10 SDK 时勾选了 Debugging Tools For Windows,那么 WinDbg 已经在如下目录内了,直接使用即可:
C://Program Files (x86)/Windows Kits/10/Debuggers/x86
如果没有,那么可以在如下地址下载安装:
https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/debugger-download-tools
安装完成后,通过菜单 File->Symbol File Path 打开符号路径设置窗口,输入如下信息:
SRV*d:\code\symbols\*https://msdl.microsoft.com/download/symbols;SRV*d:\code\symbols\*https://symbols.electronjs.org
这段配置中有三个关键信息,依次是符号文件的缓存路径、Windows 操作系统关键 dll 的符号服务器和 Electron 的符号服务器。
设置完符号服务器之后,通过菜单 File->Open Crash Dump 打开刚刚生成的崩溃报告,接着就等待 WinDbg 加载对应的符号(WinDbg 会通过 Electron 符号服务器下载与崩溃报告对应的 Electron 版本的符号文件,并保存在缓存目录中以备下次使用)。
接着再在命令窗口的底部输入 !analyze -v 指令开始分析崩溃报告。
加载完成后 WinDbg 会在窗口中显示崩溃报告内部的信息:
EXCEPTION_RECORD: (.exr -1)
ExceptionAddress: 00007ff725996fac (electron!node::AsyncResource::CallbackScope::~CallbackScope+0x000000000013227c)
ExceptionCode: c0000005 (Access violation)
ExceptionFlags: 00000000
NumberParameters: 2
Parameter[0]: 0000000000000001
Parameter[1]: 0000000000000000
Attempt to write to address 0000000000000000
PROCESS_NAME: electron.exe
WRITE_ADDRESS: 0000000000000000
ERROR_CODE: (NTSTATUS) 0xc0000005 - 0x%p 0x%p %s
EXCEPTION_CODE_STR: c0000005
EXCEPTION_PARAMETER1: 0000000000000001
EXCEPTION_PARAMETER2: 0000000000000000
STACK_TEXT:
00000053`0abf82f0 00007ff7`275a0513 : 00001c69`00000000 00000053`0abf84d8 00008d04`5e11c7b4 00001c69`00000000 : electron!node::AsyncResource::CallbackScope::~CallbackScope+0x13227c
00000053`0abf84a0 00007ff7`275a0121 : 00008d04`5e11c7a4 00000053`0abf8690 00007ff7`2b7e55c0 0000452c`0087b1bb : electron!v8::Object::SlowGetInternalField+0x7f3
00000053`0abf84d0 00007ff7`26cacd53 : 00000000`00000000 00007ff7`26c1f112 00000000`00000000 00000000`06b96722 : electron!v8::Object::SlowGetInternalField+0x401
00000053`0abfcfe0 00007ff7`26652c61 : 00000000`00000000 00001c69`08042229 00001c69`c0cdb000 00001c69`08282125 : electron!v8::V8::ToLocalEmpty+0x2193
00000053`0abfd010 00007ff7`27720c24 : 00000000`00000000 00000000`00000000 00000053`0abfd068 00000000`00000000 : electron!v8::Value::ToString+0x2eef1
00000053`0abfd050 00007ff7`251fa720 : 00000000`00000000 00000000`00000000 00000000`00000000 00001c69`a5e82115 : electron!v8::internal::TickSample::Init+0x11a24
00000053`0abfd0d0 00007ff7`25ae571c : 00000000`00000000 00000053`0abfd218 00001c69`a5e80000 00000000`00000002 : electron!v8::Isolate::CreateParams::~CreateParams+0xce60
00000053`0abfd130 00001c69`000c6308 : 00000000`0d72ce44 00001c69`08942dd9 00000000`06b96722 00001c69`08582e0d : electron!v8_inspector::protocol::Binary::operator=+0x6f12c
00000053`0abfd188 00000000`0d72ce44 : 00001c69`08942dd9 00000000`06b96722 00001c69`08582e0d 00000000`0d72ce44 : 0x00001c69`000c6308
00000053`0abfd190 00001c69`08942dd9 : 00000000`06b96722 00001c69`08582e0d 00000000`0d72ce44 00001c69`0946344d : 0xd72ce44
00000053`0abfd198 00000000`06b96722 : 00001c69`08582e0d 00000000`0d72ce44 00001c69`0946344d 00001c69`088c2349 : 0x00001c69`08942dd9
00000053`0abfd1a0 00001c69`08582e0d : 00000000`0d72ce44 00001c69`0946344d 00001c69`088c2349 00001c69`08582e0d : 0x6b96722
00000053`0abfd1a8 00000000`0d72ce44 : 00001c69`0946344d 00001c69`088c2349 00001c69`08582e0d 00001c69`083d6e61 : 0x00001c69`08582e0d
00000053`0abfd1b0 00001c69`0946344d : 00001c69`088c2349 00001c69`08582e0d 00001c69`083d6e61 00001c69`08584a49 : 0xd72ce44
00000053`0abfd1b8 00001c69`088c2349 : 00001c69`08582e0d 00001c69`083d6e61 00001c69`08584a49 00000000`0000069c : 0x00001c69`0946344d
00000053`0abfd1c0 00001c69`08582e0d : 00001c69`083d6e61 00001c69`08584a49 00000000`0000069c 00000000`0000645c : 0x00001c69`088c2349
00000053`0abfd1c8 00001c69`083d6e61 : 00001c69`08584a49 00000000`0000069c 00000000`0000645c 00001c69`08942dd9 : 0x00001c69`08582e0d
00000053`0abfd1d0 00001c69`08584a49 : 00000000`0000069c 00000000`0000645c 00001c69`08942dd9 00000000`000000e8 : 0x00001c69`083d6e61
00000053`0abfd1d8 00000000`0000069c : 00000000`0000645c 00001c69`08942dd9 00000000`000000e8 00001c69`08605fed : 0x00001c69`08584a49
00000053`0abfd1e0 00000000`0000645c : 00001c69`08942dd9 00000000`000000e8 00001c69`08605fed 00000000`00000000 : 0x69c
00000053`0abfd1e8 00001c69`08942dd9 : 00000000`000000e8 00001c69`08605fed 00000000`00000000 00001c69`08942de9 : 0x645c
00000053`0abfd1f0 00000000`000000e8 : 00001c69`08605fed 00000000`00000000 00001c69`08942de9 00001c69`088c2349 : 0x00001c69`08942dd9
00000053`0abfd1f8 00001c69`08605fed : 00000000`00000000 00001c69`08942de9 00001c69`088c2349 00000053`0abfd2c8 : 0xe8
00000053`0abfd200 00000000`00000000 : 00001c69`08942de9 00001c69`088c2349 00000053`0abfd2c8 00007ff7`25a7ed0f : 0x00001c69`08605fed
SYMBOL_NAME: electron!node::AsyncResource::CallbackScope::~CallbackScope+13227c
MODULE_NAME: electron
IMAGE_NAME: electron.exe
STACK_COMMAND: ~0s ; .ecxr ; kb
FAILURE_BUCKET_ID: NULL_POINTER_WRITE_c0000005_electron.exe!node::AsyncResource::CallbackScope::_CallbackScope
OSPLATFORM_TYPE: x64
OSNAME: Windows 10
FAILURE_ID_HASH: {3f18c3a4-c6fc-f39e-d02b-f38f7b21394d}
Followup: MachineOwner
上面这段错误信息分为两部分,一部分是 EXCEPTION_RECORD 节,其中 ExceptionAddress 是崩溃产生时的代码执行地址。
这里面的信息为:错误发生在一个异步回调方法内(electron!node::AsyncResource::CallbackScope),ExceptionCode 是 Windows API 中 GetLastError 获取到的错误码(c0000005 Access violation,访问被禁止)。
Windows 定义了很多错误码,如果你在调试崩溃报告时,遇到了不一样的错误码,可以在这个页面查询错误码的具体含义:docs.microsoft.com/en-us/windo… 。
接下来还有一行错误:Attempt to write to address 0000000000000000,说明程序试图在某个内存地址写入信息时出错。
另一部分是 STACK_TEXT 节,这个节显示的是堆栈信息,也就是崩溃前 C++ 代码的执行情况,在这里可以看到更明确的错误现场,其中有 7 行是与 V8 引擎执行有关的信息,说明代码发生在 JavaScript 脚本执行期间。
使用 WinDbg 分析崩溃报告设置比较烦琐,为此社区内有人专门开发了一个崩溃报告分析工具:electron-minidump 。
这个工具会自动帮开发者下载符号文件,执行分析指令。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论