
你是不是也遇到过这种情况Qt 程序在开发机上怎么跑都没事一发给用户运行几天后突然闪退。事件查看器里只有一句“Faulting application name: MyApp.exe”没日志、没交互、没复现步骤。我接手这类问题第一件事就是确认程序有没有生成 Dump 文件。Dump 文件是 Windows 下 Windows Error ReportingWER或代码主动生成的内存快照里面保留了崩溃时刻的线程栈、寄存器、加载模块甚至完整的进程内存。配合 MSVC 2022 64bit 编译出的 PDB 符号文件就能在本地还原出崩溃发生在哪个函数、哪一行、哪个参数上。这篇文章会完整走一遍 Qt Creator 环境下从工具链配置、Dump 自动生成到用 WinDbg 做崩溃栈分析的流程包括注册表 WER 零代码方案和代码兜底方案最后列一份我踩过多次的坑位清单。1. 为什么必须给 Qt 程序配一套 Dump 生成机制Release 环境崩溃排查的痛点1.1 发布版程序崩溃时的“三无”状态开发阶段的崩溃排查很简单Qt Creator 里按 F5调试器停在崩溃行看调用栈和变量就够了。但发布版完全是另一回事。发布版程序一旦交到用户手里基本处于“三无状态”没有调试器可以挂上去没有可交互的控制台也不一定有任何有效日志。普通用户能提供的信息往往只有“点了某个按钮就闪退”“运行了大概半小时没了”。如果这个崩溃还和业务数据相关复现成本会高到难以接受。在 Qt 程序里这个问题尤其明显。QWidget/QML 的事件循环会把用户交互、定时器回调、信号槽调度都压在同一个线程里一旦出现内存越界或者悬空指针很可能不是马上崩溃而是要等到下一次事件循环或者析构时才炸。这种延迟崩溃在开发机上几乎无法稳定复现。1.2 Dump 文件到底保存了什么Dump 文件本质上是进程崩溃瞬间的一个“尸检快照”最常见的两类内容迷你转储MiniDump线程栈、寄存器、模块信息、异常记录体积通常只有几十 MB 到几百 MB。完整转储Full Dump额外包含进程的完整内存空间体积可能上 GB但能用来直接分析堆内存内容、字符串、加载的资源文件。我个人的经验是编程式主动转储时默认生成“完整内存 未加载模块 句柄数据”的最小集合保证栈回溯的信息足够同时尽量控制体积。注册表 WER 方案则建议先用完整转储打开确认能定位问题后再根据实际情况缩小。1.3 Qt 程序的崩溃形态与 Dump 的触发边界常见的 Qt 崩溃场景大致有四类业务线程空指针/野指针例如 QPointer 使用不当或者跨越线程 delete 了 QObject。Qt 绘制或 QML 场景图崩溃栈顶往往出现在 Qt6Gui.dll、Qt6Quick.dll 里还经常伴随图形驱动相关模块。第三方原生库OpenSSL、SQLite、SDK内部越界崩溃栈会直接扎进对方 DLL。静态对象析构顺序问题退出主事件循环后崩溃。这四类问题里只有第一类还可以靠日志猜出来其余三类基本必须靠 Dump。所以我的原则很简单任何要发布出去的 Qt 程序必须带 Dump 生成能力这是发布清单的必选项不是可选项。2. MSVC 2022 64bit 工具链配置从 Kit 选择到 PDB 符号保存Dump 分析的价值取决于能不能把崩溃地址翻译成函数名。如果编译器是 MSVC那么 PDB 符号文件就是翻译桥梁。很多人在 Qt 安装和 Kit 配置这一步就埋下了隐患。2.1 安装器里必须选对 Qt 版本套件用 Qt 在线安装器时很多人默认只选 MinGW 套件因为安装快、开箱即用。结果就是 Qt Creator 的 Kit 列表里根本没有 MSVC 2022 64bit 选项。要做 MSVC 工具链安装器里需要同时选中Qt 版本对应的 MSVC 2022 64bit 模块例如 Qt 6.5.2 下面的MSVC 2019 64-bit或MSVC 2022 64-bit选项。如果机器上没有 Visual Studio至少安装“Visual Studio 2022 Build Tools”其中勾选“使用 C 的桌面开发”。这里强调一点MSVC 2022 64bit 的 Qt 库和 MinGW 的 Qt 库二进制 ABI 不兼容。你用 MSVC 编译器去链接 MinGW 版 Qt 的 lib链接器会直接报一堆无法解析的外部符号或者运行时莫名其妙的崩溃。Qt Creator 里 Kit 的编译器、Qt 版本、调试器必须组合成套不要手动混搭。2.2 Kit 配置里三个最容易出错的位置进入工具 - 选项 - Kits后可以看到已检测到的工具链。手动创建 Kit 时我习惯按顺序检查三项编译器必须选择Microsoft Visual C Compiler 17.x x64对应 MSVC 2022。如果这里选的 C 和 C 编译器不一致构建出来要么没法链接要么会有运行时问题。Qt 版本选择安装时带 MSVC 字样的 qmake 路径。路径里通常能看到Qt\6.5.2\msvc2019_64\bin\qmake.exe。调试器建议选择 Windows SDK 自带的 CDBcdb.exe。如果 Kit 调试器为空QWidget 程序里的某些异常排查会不方便后面第 6 章会专门讲。配好后先编译一个空窗口程序看“编译输出”里是否出现cl.exe和link.exe。如果出现的是g说明 Kit 还是 MinGW赶紧回头改。2.3 PDB 符号文件Release 版也必须留很多 Qt 开发者只在 Debug 构建里保留调试信息Release 版直接CONFIG release一把梭。到了分析 dump 那天WinDbg 里全是裸地址等于白看。MSVC 下 Release 版完全可以同时产出优化后的代码和 PDB 符号。qmake 工程里我一般这样写CONFIG release CONFIG force_debug_info QMAKE_CXXFLAGS_RELEASE /Zi /O2 /Ob2 QMAKE_LFLAGS_RELEASE /DEBUG /OPT:REF /OPT:ICFCMake 工程则这样set(CMAKE_BUILD_TYPE Release) set(CMAKE_CXX_FLAGS_RELEASE /O2 /Ob2 /Zi) set(CMAKE_EXE_LINKER_FLAGS_RELEASE /DEBUG /OPT:REF /OPT:ICF)用/DEBUG让链接器生成 PDB同时OPT:REF和OPT:ICF会裁掉未引用函数并合并相同 COMDAT不会因为保留调试信息就让发布体积明显变大。生成的.pdb文件一定要随构建版本一起归档最好按版本号单独存目录比如symbols\v2.3.0\。这里必须提醒发布给用户的只需要 exe/dll但 PDB 绝不能发布也绝不能丢。丢了 PDB崩溃地址就还原不出函数名Dump 分析价值立刻下降大半。2.4 为什么我坚持不用 “Release 版 Release Qt 库” 的默认 Release 配置有人可能会问Release Qt 库本身不是没有调试符号吗那我生成 Release 版 PDB 有什么用Qt 官方安装的 MSVC Release 库确实不一定带公开符号但这不影响你分析自己代码的崩溃栈。只要你自己程序模块的 PDB 在WinDbg 就能把栈顶的MyApp.exe!WorkerThread::run0x12c解析出来。至于栈下游的 Qt 库内部帧很多只是显示成Qt6Core.dll0x3a1b没关系它至少能告诉我们崩溃发生在 Qt 库的哪个阶段。如果连 Qt 库也想看得更细可以自己用源码编译 Qt 并生成符号但一般项目不需要走到这一步性价比不高。优先保证自己代码符号完整已经能解决绝大多数问题。3. 零代码方案注册表 LocalDumps 的完整配置与一键部署如果只想要一个“崩溃时自动留下 Dump 文件”的能力而且不想改任何代码Windows 自带的 WER LocalDumps 注册表配置是最快的方案。3.1 LocalDumps 注册表参数说明LocalDumps 是 WER 提供的一个本地转储子功能。我们可以在注册表里为指定 exe 单独配置转储行为位置是HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps如果目标程序是 32bit 应用在 64bit Windows 上还要看另一个镜像路径HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\Windows Error Reporting\LocalDumps每个子键对应一个应用程序名例如MyApp.exe。关键值如下值名类型说明DumpFolderREG_EXPAND_SZDump 输出目录默认是%LOCALAPPDATA%\CrashDumpsDumpTypeREG_DWORD常见取值1 为迷你转储2 为完整转储3 为迷你转储附带堆内容DumpCountREG_DWORD该 exe 最多保留多少个 dump默认 10超出自动清理DumpType 的取舍。完整转储2信息最全但 Qt 程序动辄占用几百 MB 内存完整转储可能生成 1-2 GB 文件不适合长期开启。我通常先临时设置为 2定位几次后再降为 1 常驻。3.2 一键部署与清理脚本公司内部部署时我最常用的是一个管理员权限的批处理脚本。比如给MyApp.exe配置到D:\CrashDumpsecho off setlocal :: 创建目录 mkdir D:\CrashDumps 2NUL :: 删除可能存在的旧配置保证幂等 reg delete HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\MyApp.exe /f NUL 21 :: 写入新配置 reg add HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\MyApp.exe /v DumpFolder /t REG_EXPAND_SZ /d D:\CrashDumps /f reg add HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\MyApp.exe /v DumpType /t REG_DWORD /d 2 /f reg add HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\MyApp.exe /v DumpCount /t REG_DWORD /d 20 /f echo LocalDumps configured.如果程序名经常变可以把批处理参数化。部署后让用户重新启动一次程序不用重启操作系统但要注意WER 读取配置的时机是进程启动时正在运行中的旧进程不会按新配置生效。个人建议不要把所有 exe 都塞到同一个LocalDumps根键下不同模块各自建子键方便按程序分类归档。3.3 如何快速验证 Dump 真的能生成配置完成后可以先手动制造崩溃来验证。最稳妥的方式是在你的代码里临时加一个测试按钮或者用命令行参数触发if (qEnvironmentVariableIsSet(FORCE_CRASH)) { volatile int* p nullptr; *p 0xDEAD; }编译出一个带该逻辑的测试版本跑一次然后去D:\CrashDumps目录看是否多出.dmp文件。这时候生成的 dump 文件名一般是MyApp.exe.随机串.dmp。验证完成后记得把FORCE_CRASH逻辑移除避免正式版本里留这种危险入口。4. 代码兜底方案SetUnhandledExceptionFilter MiniDumpWriteDump 实现自主转储注册表方案虽然简单但它依赖系统配置用户机器被安全软件清理、组策略限制或者权限异常时WER 可能不会落盘。所以我更推荐在代码里主动做一套 Dump 生成逻辑让程序自己掌握“崩溃现场证据”。4.1 为什么还需要代码方案代码主动转储有几个好处不依赖目标机器注册表和 WER 策略。Dump 文件名可以自己定义比如带上版本号和精确时间。可以在写 dump 前把当前状态追加到日志。可以控制转储类型长期常驻用迷你转储避免磁盘爆炸。缺点也很明显进程异常崩溃后处理器上下文可能已经处于非常微妙的状态转储代码调用的 Windows API 越少越安全。所以这部分代码要写得保守别在崩溃处理器里构建复杂对象。4.2 MiniDumpWriteDump 的关键参数核心 API 是dbghelp.dll里的MiniDumpWriteDump。我常用的一组参数MiniDumpWithFullMemory | MiniDumpWithUnloadedModules | MiniDumpWithHandleDataMiniDumpWithFullMemory会写入完整内存好处是即使某个崩溃地址指向的对象已经释放也有机会在 dump 里翻出旧内存内容。MiniDumpWithUnloadedModules用来保留已被卸载模块的加载信息对插件型应用很有用。MiniDumpWithHandleData可以看句柄表分析资源泄漏时用到。如果担心体积可以把MiniDumpWithFullMemory换成MiniDumpWithDataSegs | MiniDumpWithProcessThreadData。但首次排查建议先完整转储一次。4.3 一套可以直接抄的崩溃处理代码下列代码我实际在多个 Qt 项目里用过核心逻辑刻意保持纯 Windows API避免在崩溃处理器里构造 QString、QDir 等对象引发二次崩溃#include windows.h #include dbghelp.h #include cstdio static LONG WINAPI CrashDumpHandler(EXCEPTION_POINTERS* exceptionPointers) { wchar_t modulePath[MAX_PATH] { 0 }; DWORD pathLen GetModuleFileNameW(nullptr, modulePath, MAX_PATH); if (pathLen 0 || pathLen MAX_PATH) { return EXCEPTION_EXECUTE_HANDLER; } // 构造 dump 文件名MyApp.exe_20250810_143025.dmp SYSTEMTIME st; GetLocalTime(st); wchar_t dumpPath[MAX_PATH] { 0 }; swprintf_s(dumpPath, L%s_%04d%02d%02d_%02d%02d%02d.dmp, modulePath, st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond); HANDLE hFile CreateFileW(dumpPath, GENERIC_WRITE, FILE_SHARE_READ, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); if (hFile INVALID_HANDLE_VALUE) { return EXCEPTION_EXECUTE_HANDLER; } MINIDUMP_EXCEPTION_INFORMATION dumpExceptionInfo {}; dumpExceptionInfo.ThreadId GetCurrentThreadId(); dumpExceptionInfo.ExceptionPointers exceptionPointers; dumpExceptionInfo.ClientPointers FALSE; MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpWithFullMemory | MiniDumpWithUnloadedModules | MiniDumpWithHandleData, dumpExceptionInfo, nullptr, nullptr); CloseHandle(hFile); // 这里可以再写一条日志但尽量使用低频、无锁方式 return EXCEPTION_EXECUTE_HANDLER; }然后在main函数最早的位置挂上int main(int argc, char* argv[]) { SetUnhandledExceptionFilter(CrashDumpHandler); QApplication app(argc, argv); // 后续初始化... return app.exec(); }这里有几个容易被忽略的语义。SetUnhandledExceptionFilter捕获的是结构化异常SEH包括空指针访问、除零、非法指令等。C 抛出的未捕获异常在 MSVC 下通常会进入std::terminate触发的是另一条路径不一定经过这个过滤器。第二个注意点是返回值EXCEPTION_EXECUTE_HANDLER。它表示当前异常已经被处理系统不会继续弹出“程序已停止工作”的对话框。如果希望系统 WER 也记录一份可以返回EXCEPTION_CONTINUE_SEARCH但通常二选一即可避免重复。4.4 与 Qt 事件循环的结合方式Qt 程序崩溃不一定都在main线程。比如 QThread 子线程里崩溃.NET 之外的原生 Windows 程序默认也会有未处理异常处理器SetUnhandledExceptionFilter的处理器会被调用配合前面的代码可以直接取到崩溃现场所以这套方式对所有线程的未处理异常都有效。不过要注意QML/JS 运行时异常不算原生崩溃不会被这个过滤器捕获。QML 里一个空对象属性访问通常会打印 warning而非触发进程级崩溃。真正要处理的是 QML 引擎 C 层的访问违规那种还是能捕获的。我个人还习惯在程序启动时检查本地是否有上次崩溃残留的 dump有机会就提示用户上传。生产环境里这套机制帮我和团队节省了大量远程排查时间。5. Dump 分析实战WinDbg 的符号配置、关键命令和一份虚拟崩溃栈解读Dump 拿到了接下来就是分析。最常用的工具是 WinDbg。如果你安装了 Windows SDK选择 64bit 版本的 Debuggers 工具x64目录来打开 64bit 程序生成的 dump。5.1 配置符号路径是第一步打开 WinDbg 后不要急着g先把符号路径设好.sympath SRV*D:\symbols*https://msdl.microsoft.com/download/symbols;D:\build\MyApp\v2.3.0 .reload命令含义SRV*D:\symbols*https://msdl.microsoft.com/download/symbols表示优先使用本地缓存找不到就去微软符号服务器下载系统 DLL 符号。;D:\build\MyApp\v2.3.0追加你自己的 PDB 目录多个路径用分号分隔。reload会让调试器重新加载模块和符号。如果看到模块列表里MyApp.exe后面有.pdb匹配说明符号挂上了。5.2 分析崩溃时最常用的命令我分析 dump 时基本固定走五步!analyze -v这条命令自动化程度最高它会给出异常类型、故障地址和建议的崩溃指令。第一次拿到 dump永远先跑它。.ecxr把线程上下文切换到异常发生时的上下文。注意打开 dump 后默认停在捕获时刻的进程状态不一定就是异常现场.ecxr会直接跳到异常记录对应的栈。k打印当前线程调用栈。加参数kb可以多显示前几个参数kp显示参数和函数原型。对遗留代码排错我会用kp。lm列出所有加载模块。如果某些模块没有符号这里会显示“无符号”警告。我会借此确认 PDB 有没有配全。!heap -p -a address如果异常是堆破坏导致!analyze -v会指向一个堆地址用这条命令进一步查看该堆块信息。5.3 一份虚拟崩溃栈的完整解读下面用一份完全虚构的崩溃栈举例。假设程序里有一个工作线程WorkerThread::run它内部调用DataLoader::load再调用一个第三方库函数third_party_parse0:000 kp # Child-SP RetAddr Call Site 00 000000000014f4c8 00007ff63a2b1a15 third_party_parse0x7f 01 000000000014f4d0 00007ff63a2b1a8c DataLoader::load0x3c 02 000000000014f4e0 00007ff63a2b1b30 WorkerThread::run0x5f 03 000000000014f4f0 00007ff63a2b1b80 thread_entry0x12 04 000000000014f500 00007ff63a2b1bd0 QThreadPrivate::start0x5a 05 000000000014f510 00007ff63a2b1c20 BaseThreadInitThunk0x10 06 000000000014f520 00007ff63a2b1c30 RtlUserThreadStart0x21寻找崩溃根因的顺序是看第 0 帧栈顶third_party_parse0x7f说明崩溃发生在第三方库内部。如果符号完整会显示库内函数名如果只有地址说明该库的 PDB 缺失。看第 1 帧DataLoader::load0x3c这是我们自己的代码立即回到源码目录打开对应行看看传给第三方库的参数是什么。看第 2 帧WorkerThread::run0x5f确认是由工作线程发起。结合!analyze -v给出的异常类型。如果是ACCESS_VIOLATION且异常地址是0x0000000000000028之类的小地址几乎可以判断是空指针解引用指向某个对象的字段。类似这样分析一次之后基本就能确定是DataLoader::load在某个边界条件下把空字符串或空结构体传给了第三方库。回到代码里加一个空值保护问题就解决了。6. Qt Creator 调试器联动用 CDB 直接复现崩溃点与按需调试有时候我们面对的不是用户 dump而是本地就能偶发复现的崩溃。这时候让 Qt Creator 直接使用 CDB 调试器比 MiniDump 分析更高效。6.1 Qt Creator 中配置 CDB在工具 - 选项 - Kits - Debuggers里点击“添加”调试器类型选择CDB路径填你安装的 Windows SDK 里的cdb.exe。例如C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\cdb.exe然后把对应的 Kit 的“调试器”字段改成这个配置。这个操作对 MSVC Kit 尤其好用因为 Qt Creator 自带 GDB 适配器通常更多用于 MinGW。6.2 直接启动调试会话配置好之后即使构建是 Release也可以不用手动挂 WinDbg直接在 Qt Creator 里点调试按钮启动。前提是 Release 版 PDB 没有删。崩溃时调试器会在反汇编窗口停在异常指令附近调用栈窗口会直接显示DataLoader::load这类函数名。这里有个很实用的小技巧如果崩溃可复现但触发位置在第三方库内部你可以直接在调试器的“表达式”窗口输入模块名和偏移地址结合反汇编对照分析。因为 MSVC 版 Qt 和第三方库通常都带一定调试信息栈回溯比纯手工算地址快很多。6.3 从已有 Dump 打开分析Qt Creator 本身不擅长直接打开.dmp更顺手的做法是在 WinDbg 里打开 dump 后将分析结果记录到源码中对应位置。有同事也习惯把 Qt Creator 的“调试”菜单里的“起始调试/附加到进程”和本地重复测试结合起来先用 winscope 记录操作步骤再在特定步骤下触发崩溃。对我来说Qt Creator 和 CDB 的配合主要解决两类场景一类是本地马上能复现的稳定崩溃另一类是怀疑 Qt 事件循环或信号槽时序导致的随机崩溃。前者用 Qt Creator 调试会话直接看现场后者还是回到 Dump 方案让用户机器自己留下证据再回放分析。7. 高频坑位清单与应急排查流程再稳定的方案也会翻车。这些坑几乎每个做 Qt MSVC 崩溃分析的人都遇到过我按“没生成 dump / 生成了但分析不出来 / 分析出来但定位不准”三条主线整理。7.1 Dump 没生成先查这五件事现象原因处理LocalDumps 配置了但目录没文件没有管理员权限注册或者程序启动了旧进程用管理员权限重新执行脚本确认进程重启始终没 dump但事件查看器有 WER 报告安全软件清理了转储目录换成代码主动转储输出目录改到程序安装目录只有 .wer 文件没有 .dmpDumpType 设置异常或 DumpFolder 不存在确认 REG_EXPAND_SZ 类型正确目录存在程序日志显示“dump 写入失败”dbghelp.dll 版本过旧或磁盘空间不足直接静态链接 dbghelp.lib并检查目标盘剩余空间32bit exe 在 64bit 系统上不落盘注册表被重定向到 WOW6432Node在 WOW6432Node 下同步配置或用 x64 目标重新编译7.2 Dump 打不开或栈符号对不上最常见的问题是 PDB 与 exe 构建不一致。每次代码改动后重新编译旧的 PDB 就不能用于新 dump。WinDbg 加载时会提示“pdb mismatched”此时别强行继续回到对应版本的符号目录找正确的 PDB。还有一个高频问题栈顶全是一堆偏移地址没有函数名。这不是 dump 坏了而是模块没有挂上符号。检查模块列表lm看目标模块后面是否显示.pdb。没有的话把符号路径改到该版本的 PDB 目录再reload。Release 优化导致的栈地址不可靠也容易误判。开启/O2后编译器可能做内联和尾调用优化崩溃栈看起来会少几层。分析这类栈时我会重点关注异常记录指向的指令地址回到反汇编窗口看这个地址是不是位于某个函数的中间。7.3 第三方库崩溃时的处理思路如果崩溃栈显示崩溃点不在自己代码而在某个 SDK 库或系统库里不要急着下结论。先用lm看加载模块列表再检查是不是有多个同名 DLL 被加载了老版本。举个我踩过的真实教训产品安装包里带了旧的opengl32.dll或第三方渲染库的调试版结果用户机器上图形模块崩溃栈一直扎在显卡驱动里。如果不是靠 dump 里完整的模块列表根本想不到是安装包的版本覆盖问题。遇到这种情况建议在 dump 分析时额外执行lmvm 有问题的模块名这条命令会显示模块的版本、时间戳、符号路径。如果版本号和已发布版本集不一致优先检查程序启动路径下是否存在同名的旧 DLL。7.4 个人经验崩溃现场管理远比分析重要处理过几十个崩溃问题后我最深的体会是真正花的力气常常不在 WinDbg 命令上而在崩溃现场的完整管理上。我现在习惯在项目里做三件事建立一个“符号归档”目录按 git 提交号或版本号保存 PDB和 exe 安装包同版本存储。这样任何一台上线机器的崩溃 dump 都能匹配到正确符号。代码生成的 dump 文件名带上版本号例如MyApp_2.3.0_20250810_143025.dmp。排查时一眼就能看出是哪个版本号出的事不用再次导出元数据。程序启动时检查本地是否有残留 dump有就在启动后的空闲时机上传到专用崩溃收集目录文件名附带用户机器标识。这样客户端崩溃第二天早上就能看到一批待分析的 dump 文件。第 3 点对 Qt 程序尤其有价值。Qt 的异常在 Release 版里经常是偶发性的用户那边可能只崩溃一次就不复现如果 dump 及时收集回来往往比你说的“当时点了什么按钮”要靠谱得多。最后补充一个关于 dump 安全性的常识完整转储包含进程内存快照里面可能会有用户敏感数据或密钥。如果应用面向敏感业务建议默认只保留迷你转储并在完整转储生成后尽快加密或脱敏处理不要把完整转储长期留在用户本机目录里。