文章目录
- 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#include<chrono>#include<filesystem>#include<fstream>#include<iomanip>#include<iostream>#include<mutex>#include<string>#include<sstream>#include<vector>// 平台特定头文件#ifdef_WIN32#include<windows.h>#include<dbghelp.h>#pragmacomment(lib,"Dbghelp.lib")#else#include<signal.h>#include<unistd.h>#include<execinfo.h>// 用于 macOS 获取基础堆栈#endif#pragmawarning(push)#pragmawarning(disable:4996)#include<glog/logging.h>#include<glog/raw_logging.h>#pragmawarning(pop)namespacefs=std::filesystem;usingnamespacestd::chrono_literals;classGLogWrapper{public:structConfig{fs::path log_dir="logs";std::string program_name="application";intmax_log_size=100;intmin_log_level=google::GLOG_INFO;boollog_to_stderr=true;intstderr_threshold=google::GLOG_ERROR;boolenable_stacktrace_on_crash=true;fs::path crash_log_path="crash_dump.log";};staticboolInitialize(constConfig&config){std::lock_guard<std::mutex>lock(init_mutex_);if(initialized_)returntrue;config_=config;try{if(!fs::exists(config_.log_dir)){fs::create_directories(config_.log_dir);}}catch(conststd::exception&e){std::cerr<<"Create log dir failed: "<<e.what()<<std::endl;returnfalse;}FLAGS_log_dir=config_.log_dir.string();FLAGS_max_log_size=config_.max_log_size;FLAGS_minloglevel=config_.min_log_level;FLAGS_alsologtostderr=config_.log_to_stderr;FLAGS_stderrthreshold=config_.stderr_threshold;FLAGS_colorlogtostderr=true;google::InitGoogleLogging(config_.program_name.c_str());if(config_.enable_stacktrace_on_crash){InstallCrashHandler();}initialized_=true;returntrue;}staticvoidShutdown(){std::lock_guard<std::mutex>lock(init_mutex_);if(initialized_){google::ShutdownGoogleLogging();initialized_=false;}}private:staticinlineboolinitialized_=false;staticinlinestd::mutex init_mutex_;staticinlineConfig config_;staticstd::stringGetTimestampSafe(){autonow=std::chrono::system_clock::now();std::time_t now_c=std::chrono::system_clock::to_time_t(now);std::tm result{};#ifdef_WIN32localtime_s(&result,&now_c);#elselocaltime_r(&now_c,&result);#endifstd::stringstream ss;ss<<std::put_time(&result,"%Y-%m-%d %H:%M:%S");returnss.str();}staticvoidWriteCrashData(conststd::string&data,constchar*reason){fs::path final_path=config_.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<<"\n"<<std::string(70,'=')<<"\n";crash_file<<"["<<GetTimestampSafe()<<"] SOURCE: "<<reason<<"\n";crash_file<<data;crash_file<<"\n"<<std::string(70,'=')<<"\n";crash_file.flush();}std::cerr<<"\n!!! CRASH DETECTED ["<<reason<<"] !!!\n"<<data<<std::endl;}#ifdef_WIN32// Windows 专用:SEH 异常过滤staticLONG WINAPIWindowsExceptionFilter(EXCEPTION_POINTERS*ExceptionInfo){std::stringstream ss;ss<<"Exception Code: 0x"<<std::hex<<ExceptionInfo->ExceptionRecord->ExceptionCode<<std::dec<<"\n";ss<<"Stack Trace:\n"<<google::GetStackTrace();WriteCrashData(ss.str(),"Windows SEH Handler");returnEXCEPTION_EXECUTE_HANDLER;}#else// Mac/Linux 专用:POSIX 信号处理staticvoidPosixSignalHandler(intsig){std::stringstream ss;ss<<"Caught Signal: "<<sig<<" ("<<strsignal(sig)<<")\n";ss<<"Stack Trace:\n"<<google::GetStackTrace();WriteCrashData(ss.str(),"POSIX Signal Handler");_exit(sig);// 信号处理中建议使用 _exit}#endifstaticvoidInstallCrashHandler(){// 1. 捕获 LOG(FATAL)google::InstallFailureFunction([](){std::string stack=google::GetStackTrace();WriteCrashData("Fatal Error.\nStack Trace:\n"+stack,"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_handler=PosixSignalHandler;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测试文件
#include"GLogWrap.hpp"#include<iostream>//intmain(){// 1. 配置初始化GLogWrapper::Config config;config.log_dir="D:/logs";// 确保该路径在 Windows 下有写入权限config.program_name="MyApp";config.enable_stacktrace_on_crash=true;config.crash_log_path="D:/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. 模拟业务逻辑inta=10;intb=0;std::cout<<"准备触发除零崩溃..."<<std::endl;// 注意:在某些编译器优化下,除零可能会被直接优化掉或者变成运行时异常// 这里使用 volatile 防止编译器优化volatileintv_a=a;volatileintv_b=b;LOG_INFO<<"正在计算 v_a / v_b ...";// 触发崩溃// glog 的信号处理器会捕获此处的 SIGFPE 并调用我们定义的 FailureWriterintc=v_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_dir="logs";// 日志目录std::string program_name="application";// 程序名intmax_log_size=100;// 最大日志文件大小(MB)intmin_log_level=google::GLOG_INFO;// 最小日志级别boollog_to_stderr=true;// 是否输出到终端intstderr_threshold=google::GLOG_ERROR;// 终端输出阈值boolenable_stacktrace_on_crash=true;// 崩溃时生成堆栈fs::path crash_log_path="crash_dump.log";// 崩溃日志路径};2.核心功能
初始化与清理
Initialize(): 初始化 glog 库,创建日志目录,配置日志参数Shutdown(): 安全关闭日志系统
崩溃处理机制
实现了三层崩溃捕获:
- LOG(FATAL) 捕获:捕获程序主动触发的致命错误
- GLog 内部错误捕获:捕获 glog 库自身的错误
- 系统级崩溃捕获:
- Windows: SEH (结构化异常处理) 异常过滤
- Mac/Linux: POSIX 信号处理 (SIGSEGV, SIGFPE, SIGILL, SIGBUS)
3.跨平台支持
- Windows: 使用
SetUnhandledExceptionFilter()和 SEH - Mac/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_name="MyApp";// 初始化if(LOG_INIT(config)){LOG_INFO<<"Application started";LOG_WARN<<"This is a warning";LOG_ERROR<<"An error occurred";// 程序运行...// 关闭LOG_SHUTDOWN();}优点
- 线程安全:使用互斥锁保护初始化过程
- 异常安全:使用 RAII 和 try-catch 处理文件操作异常
- 崩溃恢复友好:独立记录崩溃信息,便于问题定位
- 配置灵活:提供详细的配置选项
- 跨平台:统一接口,屏蔽平台差异
这个包装器特别适合需要稳定日志记录和崩溃分析的服务器程序或关键应用。