// crash_handler.h - 崩溃现场捕获与死因日志 // // 解决问题:程序在客户机上"双击后无声消失",控制台一闪而过、运行日志(run.log) // 因缓冲未落盘而什么都不剩,无法定位原因。 // // 本模块在 main() 最开头安装以下钩子,任何一条被触发都会把死因写入 // /YYYYMMDD/crash.log (默认 data/YYYYMMDD/crash.log) // 写失败时自动回退到 exe 同目录 crash.log,再回退到系统临时目录。 // // 捕获范围(Windows): // - SEH 异常:访问违规 0xC0000005、栈溢出 0xC00000FD、除零 0xC0000094、 // 非法指令 0xC000001D、DLL 未找到/初始化失败等(SetUnhandledExceptionFilter) // - abort():未处理异常 / 断言失败 / std::thread 析构时仍 joinable(SIGABRT) // - std::terminate:未捕获的 C++ 异常(std::set_terminate) // - new 失败:std::bad_alloc(std::set_new_handler) // 记录内容:异常码+含义、出错地址(模块+偏移)、符号名与源码行号(有 dbghelp 时)、 // 完整调用栈、崩溃前最后一个"里程碑"、并生成 .dmp 供事后用 VS/WinDbg 分析。 // // 使用: // install_crash_handlers(); // main() 第一行 // CRASH_MILESTONE("配置加载完成"); // 关键节点打点,崩溃时一并输出 #ifndef CRASH_HANDLER_H #define CRASH_HANDLER_H // 安装全部崩溃钩子;可重复调用(幂等)。log_dir 为崩溃日志根目录(相对当前工作目录)。 void install_crash_handlers(const char* log_dir = "data"); // 记录运行里程碑:同时打印到控制台(进 run.log)并记住最后一条, // 崩溃时一并写入 crash.log,用于判断"程序死在哪一步"。printf 风格。 void crash_milestone(const char* fmt, ...); // 主动写一条严重错误(不终止进程),printf 风格。 void crash_log(const char* fmt, ...); // 便捷宏 #define CRASH_MILESTONE(...) crash_milestone(__VA_ARGS__) #define CRASH_LOG(...) crash_log(__VA_ARGS__) #endif // CRASH_HANDLER_H