使用glog记录崩溃堆栈

📅 发布时间:2026/7/18 7:04:15
使用glog记录崩溃堆栈 文章目录GlogWrap.hpp测试文件崩溃堆栈主要特性1. **配置结构 (Config)**2. **核心功能**初始化与清理崩溃处理机制3. **跨平台支持**4. **崩溃信息记录**5. **宏定义简化使用**使用示例优点GlogWrap.hpp#ifndefSAFE_GLOG_WRAPPER_H#defineSAFE_GLOG_WRAPPER_H#defineGLOG_NO_ABBREVIATED_SEVERITIES#defineGLOG_USE_GLOG_EXPORT#ifndefNOMINMAX#defineNOMINMAX#endif#includechrono#includefilesystem#includefstream#includeiomanip#includeiostream#includemutex#includestring#includesstream#includevector// 平台特定头文件#ifdef_WIN32#includewindows.h#includedbghelp.h#pragmacomment(lib,Dbghelp.lib)#else#includesignal.h#includeunistd.h#includeexecinfo.h// 用于 macOS 获取基础堆栈#endif#pragmawarning(push)#pragmawarning(disable:4996)#includeglog/logging.h#includeglog/raw_logging.h#pragmawarning(pop)namespacefsstd::filesystem;usingnamespacestd::chrono_literals;classGLogWrapper{public:structConfig{fs::path log_dirlogs;std::string program_nameapplication;intmax_log_size100;intmin_log_levelgoogle::GLOG_INFO;boollog_to_stderrtrue;intstderr_thresholdgoogle::GLOG_ERROR;boolenable_stacktrace_on_crashtrue;fs::path crash_log_pathcrash_dump.log;};staticboolInitialize(constConfigconfig){std::lock_guardstd::mutexlock(init_mutex_);if(initialized_)returntrue;config_config;try{if(!fs::exists(config_.log_dir)){fs::create_directories(config_.log_dir);}}catch(conststd::exceptione){std::cerrCreate log dir failed: e.what()std::endl;returnfalse;}FLAGS_log_dirconfig_.log_dir.string();FLAGS_max_log_sizeconfig_.max_log_size;FLAGS_minloglevelconfig_.min_log_level;FLAGS_alsologtostderrconfig_.log_to_stderr;FLAGS_stderrthresholdconfig_.stderr_threshold;FLAGS_colorlogtostderrtrue;google::InitGoogleLogging(config_.program_name.c_str());if(config_.enable_stacktrace_on_crash){InstallCrashHandler();}initialized_true;returntrue;}staticvoidShutdown(){std::lock_guardstd::mutexlock(init_mutex_);if(initialized_){google::ShutdownGoogleLogging();initialized_false;}}private:staticinlineboolinitialized_false;staticinlinestd::mutex init_mutex_;staticinlineConfig config_;staticstd::stringGetTimestampSafe(){autonowstd::chrono::system_clock::now();std::time_t now_cstd::chrono::system_clock::to_time_t(now);std::tm result{};#ifdef_WIN32localtime_s(result,now_c);#elselocaltime_r(now_c,result);#endifstd::stringstream ss;ssstd::put_time(result,%Y-%m-%d %H:%M:%S);returnss.str();}staticvoidWriteCrashData(conststd::stringdata,constchar*reason){fs::path final_pathconfig_.crash_log_path.is_absolute()?config_.crash_log_path:config_.log_dir/config_.crash_log_path;try{fs::create_directories(final_path.parent_path());}catch(...){}std::ofstreamcrash_file(final_path,std::ios::app);if(crash_file.is_open()){crash_file\nstd::string(70,)\n;crash_file[GetTimestampSafe()] SOURCE: reason\n;crash_filedata;crash_file\nstd::string(70,)\n;crash_file.flush();}std::cerr\n!!! CRASH DETECTED [reason] !!!\ndatastd::endl;}#ifdef_WIN32// Windows 专用SEH 异常过滤staticLONG WINAPIWindowsExceptionFilter(EXCEPTION_POINTERS*ExceptionInfo){std::stringstream ss;ssException Code: 0xstd::hexExceptionInfo-ExceptionRecord-ExceptionCodestd::dec\n;ssStack Trace:\ngoogle::GetStackTrace();WriteCrashData(ss.str(),Windows SEH Handler);returnEXCEPTION_EXECUTE_HANDLER;}#else// Mac/Linux 专用POSIX 信号处理staticvoidPosixSignalHandler(intsig){std::stringstream ss;ssCaught Signal: sig (strsignal(sig))\n;ssStack Trace:\ngoogle::GetStackTrace();WriteCrashData(ss.str(),POSIX Signal Handler);_exit(sig);// 信号处理中建议使用 _exit}#endifstaticvoidInstallCrashHandler(){// 1. 捕获 LOG(FATAL)google::InstallFailureFunction([](){std::string stackgoogle::GetStackTrace();WriteCrashData(Fatal Error.\nStack Trace:\nstack,LOG(FATAL));abort();});// 2. 捕获 GLog 内部 FailureWritergoogle::InstallFailureWriter([](constchar*data,size_t size){WriteCrashData(std::string(data,size),GLog FailureWriter);});#ifdef_WIN32SetUnhandledExceptionFilter(WindowsExceptionFilter);SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOGPFAULTERRORBOX);#else// 3. Mac 下安装信号监听structsigactionsa;memset(sa,0,sizeof(sa));sa.sa_handlerPosixSignalHandler;sigfillset(sa.sa_mask);sigaction(SIGSEGV,sa,nullptr);// 段错误内存非法访问sigaction(SIGFPE,sa,nullptr);// 算术异常除零sigaction(SIGILL,sa,nullptr);// 非法指令sigaction(SIGBUS,sa,nullptr);// 总线错误#endif}};#defineLOG_INIT(cfg)GLogWrapper::Initialize(cfg)#defineLOG_SHUTDOWN()GLogWrapper::Shutdown()#defineLOG_INFOLOG(INFO)#defineLOG_WARNLOG(WARNING)#defineLOG_ERRORLOG(ERROR)#defineLOG_FATALLOG(FATAL)#endif测试文件#includeGLogWrap.hpp#includeiostream//intmain(){// 1. 配置初始化GLogWrapper::Config config;config.log_dirD:/logs;// 确保该路径在 Windows 下有写入权限config.program_nameMyApp;config.enable_stacktrace_on_crashtrue;config.crash_log_pathD:/logs/myapp_crash.log;// 2. 启动日志系统if(!LOG_INIT(config)){std::cerr日志初始化失败std::endl;return-1;}LOG_INFO程序启动日志目录: config.log_dir;LOG_WARN这是一条警告日志;//LOG_ERROR 这是一条错误日志;// 3. 模拟业务逻辑inta10;intb0;std::cout准备触发除零崩溃...std::endl;// 注意在某些编译器优化下除零可能会被直接优化掉或者变成运行时异常// 这里使用 volatile 防止编译器优化volatileintv_aa;volatileintv_bb;LOG_INFO正在计算 v_a / v_b ...;// 触发崩溃// glog 的信号处理器会捕获此处的 SIGFPE 并调用我们定义的 FailureWriterintcv_a/v_b;// 实际上这里永远不会被执行LOG_INFO计算结果: c;LOG_SHUTDOWN();return0;}崩溃堆栈[2026-03-0521:09:50]SOURCE:Windows SEH Handler Exception Code:0xc0000094Stack Trace:00007FF78F6258B2GLogWrapper::WindowsExceptionFilter(D:\PROJ_Code\2026\use_glog\use_glog\GLogWrap.hpp:548)00007FFB131D1C4C UnhandledExceptionFilter 00007FFB15CBA53D memmove 00007FFB15C9F847 __C_specific_handler 00007FFB15CB5E9F __chkstk 00007FFB15C2E8C6 RtlFindCharInUnicodeString 00007FFB15CB4E9E KiUserExceptionDispatcher 00007FF78F63B8FDmain(D:\PROJ_Code\2026\use_glog\use_glog\use_glog_wrap.cpp:38)00007FF78F67C1F9invoke_main(D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:78)00007FF78F67C0E2__scrt_common_main_seh(D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288)00007FF78F67BF9E__scrt_common_main(D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:330)00007FF78F67C28EmainCRTStartup(D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_main.cpp:16)00007FFB13E2259D BaseThreadInitThunk 00007FFB15C6AF78 RtlUserThreadStart这是一个封装 Google Log (glog) 库的 C 包装器提供了更安全、跨平台的日志功能。让我详细解释其核心功能主要特性1.配置结构 (Config)structConfig{fs::path log_dirlogs;// 日志目录std::string program_nameapplication;// 程序名intmax_log_size100;// 最大日志文件大小(MB)intmin_log_levelgoogle::GLOG_INFO;// 最小日志级别boollog_to_stderrtrue;// 是否输出到终端intstderr_thresholdgoogle::GLOG_ERROR;// 终端输出阈值boolenable_stacktrace_on_crashtrue;// 崩溃时生成堆栈fs::path crash_log_pathcrash_dump.log;// 崩溃日志路径};2.核心功能初始化与清理Initialize(): 初始化 glog 库创建日志目录配置日志参数Shutdown(): 安全关闭日志系统崩溃处理机制实现了三层崩溃捕获LOG(FATAL) 捕获捕获程序主动触发的致命错误GLog 内部错误捕获捕获 glog 库自身的错误系统级崩溃捕获Windows: SEH (结构化异常处理) 异常过滤Mac/Linux: POSIX 信号处理 (SIGSEGV, SIGFPE, SIGILL, SIGBUS)3.跨平台支持Windows: 使用SetUnhandledExceptionFilter()和 SEHMac/Linux: 使用sigaction()安装信号处理器提供平台特定的时间戳生成函数4.崩溃信息记录当程序崩溃时会记录崩溃时间戳崩溃原因信号/异常代码完整的堆栈跟踪写入独立的崩溃日志文件5.宏定义简化使用#defineLOG_INIT(cfg)// 初始化#defineLOG_SHUTDOWN()// 关闭#defineLOG_INFO// 普通日志#defineLOG_WARN// 警告日志#defineLOG_ERROR// 错误日志#defineLOG_FATAL// 致命错误使用示例// 配置GLogWrapper::Config config;config.log_dir./myapp_logs;config.program_nameMyApp;// 初始化if(LOG_INIT(config)){LOG_INFOApplication started;LOG_WARNThis is a warning;LOG_ERRORAn error occurred;// 程序运行...// 关闭LOG_SHUTDOWN();}优点线程安全使用互斥锁保护初始化过程异常安全使用 RAII 和 try-catch 处理文件操作异常崩溃恢复友好独立记录崩溃信息便于问题定位配置灵活提供详细的配置选项跨平台统一接口屏蔽平台差异这个包装器特别适合需要稳定日志记录和崩溃分析的服务器程序或关键应用。