网站500错误是什么意思,网站管理员中心,网站外包要花多少钱,wordpress 页面 编辑器前言
C 程序在运行时可能会由于 空指针访问、数组越界、非法内存访问、栈溢出 等原因崩溃。为了分析崩溃原因#xff0c;我们通常会生成 Dump 文件#xff08;Windows 的 .dmp#xff0c;Linux 的 core#xff0c;macOS 的 .crash#xff09;#xff0c;然后用调试工具分…前言
C 程序在运行时可能会由于 空指针访问、数组越界、非法内存访问、栈溢出 等原因崩溃。为了分析崩溃原因我们通常会生成 Dump 文件Windows 的 .dmpLinux 的 coremacOS 的 .crash然后用调试工具分析。 1. Windows: MiniDump 生成 .dmp 文件
Windows 提供了 MiniDumpWriteDump() API 来生成 MiniDump 文件.dmp它可以记录程序崩溃时的内存、线程、异常信息等。
1.1 MiniDumpWriteDump() 介绍
BOOL MiniDumpWriteDump(HANDLE hProcess, // 进程句柄DWORD ProcessId, // 进程 IDHANDLE hFile, // Dump 文件句柄MINIDUMP_TYPE DumpType, // Dump 类型PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, // 异常信息 (可选)PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, // 额外数据 (可选)PMINIDUMP_CALLBACK_INFORMATION CallbackParam // 回调函数 (可选)
);1.2 参数解析
参数作用hProcess进程句柄用 GetCurrentProcess() 获取ProcessId进程 ID用 GetCurrentProcessId() 获取hFile目标 Dump 文件的句柄用 CreateFile() 创建DumpTypeDump 类型控制记录多少信息ExceptionParam异常信息用于捕获崩溃时的状态可选UserStreamParam额外数据可为空CallbackParam回调函数可为空
1.3 Dump 类型MINIDUMP_TYPE
类型值十六进制描述MiniDumpNormal0x00000000默认值仅包含基本信息进程、线程、模块MiniDumpWithDataSegs0x00000001记录全局变量数据段MiniDumpWithFullMemory0x00000002完整 Dump包含所有进程内存文件较大MiniDumpWithHandleData0x00000004记录所有句柄信息MiniDumpFilterMemory0x00000008过滤一些私有的内存区域以减少 Dump 大小MiniDumpScanMemory0x00000010扫描进程内存以获取更多信息MiniDumpWithUnloadedModules0x00000020记录已卸载的模块MiniDumpWithIndirectlyReferencedMemory0x00000040记录被指针间接引用的内存内容MiniDumpFilterModulePaths0x00000080仅记录模块路径不包含完整的模块数据MiniDumpWithProcessThreadData0x00000100记录进程/线程额外信息MiniDumpWithPrivateReadWriteMemory0x00000200记录进程私有的读写内存MiniDumpWithoutOptionalData0x00000400不包含可选数据减小 Dump 大小MiniDumpWithFullMemoryInfo0x00000800记录完整的内存信息MiniDumpWithThreadInfo0x00001000记录所有线程的详细信息MiniDumpWithCodeSegs0x00002000记录代码段信息MiniDumpWithoutAuxiliaryState0x00004000不包含辅助状态信息MiniDumpWithFullAuxiliaryState0x00008000记录完整的辅助状态信息MiniDumpWithPrivateWriteCopyMemory0x00010000记录写时复制Copy-on-Write的私有内存MiniDumpIgnoreInaccessibleMemory0x00020000忽略无法访问的内存区域MiniDumpWithTokenInformation0x00040000记录进程的 Token 信息用于权限分析MiniDumpWithModuleHeaders0x00080000记录模块的 PE 头信息MiniDumpFilterTriage0x00100000仅记录用于故障诊断的最小数据集MiniDumpValidTypeFlags0x001FFFFF所有可用的 Dump 类型标志位用于验证 Dump 类型
推荐使用 MiniDumpWithDataSegs | MiniDumpWithThreadInfo可以更全面地分析崩溃原因。
1.4 自定义 Dump 文件存储路径
在 Windows 上我们可以自定义 Dump 文件的存储路径例如存放到 C:\Dumps\ 目录下
std::string dumpPath C:\\Dumps\\crash_dump.dmp;
HANDLE hFile CreateFileA(dumpPath.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);确保 C:\Dumps\ 目录存在否则 CreateFileA() 可能会失败。
1.5 Windows 代码示例
#include windows.h
#include dbghelp.h
#include iostream#pragma comment(lib, dbghelp.lib)void CreateDump(const std::string dumpPath, EXCEPTION_POINTERS* pExceptionInfo) {HANDLE hFile CreateFileA(dumpPath.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);if (hFile ! INVALID_HANDLE_VALUE) {MINIDUMP_EXCEPTION_INFORMATION dumpInfo;dumpInfo.ThreadId GetCurrentThreadId();dumpInfo.ExceptionPointers pExceptionInfo;dumpInfo.ClientPointers TRUE;MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpWithDataSegs | MiniDumpWithThreadInfo, dumpInfo, NULL, NULL);CloseHandle(hFile);}
}LONG WINAPI ExceptionHandler(EXCEPTION_POINTERS* pExceptionInfo) {std::string dumpPath C:\\Dumps\\crash_dump.dmp;CreateDump(dumpPath, pExceptionInfo);return EXCEPTION_EXECUTE_HANDLER;
}int main() {SetUnhandledExceptionFilter(ExceptionHandler);// 触发崩溃int* p nullptr;*p 10;return 0;
}1.6 Dump 分析
可以用 Visual Studio 或 WinDbg 打开 .dmp 文件查看调用栈、崩溃地址等信息。 2. Linux: Core Dump 生成
Linux 默认会生成 core 文件记录程序崩溃时的内存状态。
2.1 启用 Core Dump需要命令启动
ulimit -c unlimited # 允许生成 core dump 文件2.2 自定义 Core Dump 存储路径
可以修改 /proc/sys/kernel/core_pattern 来改变 Core Dump 存放路径例如
echo /tmp/core.%e.%p | sudo tee /proc/sys/kernel/core_pattern这样崩溃后Core Dump 文件将存放到 /tmp/ 目录并包含程序名和进程 ID。
2.3 代码示例
#include iostream
#include csignal
#include sys/resource.hvoid EnableCoreDump() {struct rlimit core_limit { RLIM_INFINITY, RLIM_INFINITY };setrlimit(RLIMIT_CORE, core_limit);
}void Crash() {int* p nullptr;*p 42;
}int main() {EnableCoreDump();Crash();return 0;
}2.4 Dump 生成路径 默认在当前目录 ./core 或 /var/lib/systemd/coredump/ 可修改 /proc/sys/kernel/core_pattern
2.5 Dump 分析
gdb ./your_program core
bt # 查看调用栈3. macOS: Crash Report需要命令启动
3.1 启用 Core Dump需要命令启动
macOS 也可能默认 禁用了 Core Dump需要运行以下命令启用
ulimit -c unlimited3.2 自定义 Core Dump 存储路径
macOS 默认将 .crash 文件存放在 ~/Library/Logs/DiagnosticReports/但可以使用 ulimit -c unlimited 后修改
echo /tmp/crash.%e.%p | sudo tee /proc/sys/kernel/core_pattern这样崩溃后Crash Report 文件会存放到 /tmp/ 目录。
3.3 代码示例
#include iostream
#include csignalvoid Crash() {int* p nullptr;*p 42;
}int main() {signal(SIGSEGV, [](int signum) {std::cerr Segmentation fault caught! std::endl;exit(1);});Crash();return 0;
}3.4 Dump 分析
lldb -c ~/Library/Logs/DiagnosticReports/YourApp.crash
bt # 查看调用栈结论
参考表如何判断崩溃原因
现象可能原因解决方法崩溃在 nullptr 访问访问空指针assert(p ! nullptr);崩溃在数组访问数组越界开启 ASan检查索引delete 崩溃释放了已释放的内存nullptr 赋值后再 delete运行一段时间后崩溃内存泄漏或数据竞争启用 Valgrind 或 ThreadSanitizerGUI 无响应死锁或 UI 线程阻塞检查 std::mutex 是否死锁
对比总结
平台默认 Dump 目录是否需要命令启动Dump 文件格式代码生成 Dump触发 Dump 的方式如何分析 Dump调试工具Windows%LOCALAPPDATA%\CrashDumps\ 或 C:\Users\用户名\AppData\Local\CrashDumps\❌ 无需命令.dmpMiniDumpWriteDump() 生成 .dmp进程崩溃自动生成 或 手动调用 MiniDumpWriteDump()WinDbg (!analyze -v)Visual Studio 直接打开 .dmpWinDbg, Visual StudioLinux./core 或 /var/lib/systemd/coredump/✅ 需要 ulimit -c unlimitedcoresetrlimit(RLIMIT_CORE, core_limit) 生成 core进程崩溃SIGSEGV 等自动生成 或 gcore 手动触发gdb 程序 core或 eu-stack -p coregdbmacOS~/Library/Logs/DiagnosticReports/✅ 需要 ulimit -c unlimited.crashsignal(SIGSEGV, handler) 生成 .crash进程崩溃SIGSEGV 等自动生成 或 lldb - process save-core 生成lldb -c crash文件atos -o 可执行文件 -p 进程IDlldb, atos