news 2026/7/18 7:04:01

使用glog记录崩溃堆栈

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
使用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#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(): 安全关闭日志系统
崩溃处理机制

实现了三层崩溃捕获:

  1. LOG(FATAL) 捕获:捕获程序主动触发的致命错误
  2. GLog 内部错误捕获:捕获 glog 库自身的错误
  3. 系统级崩溃捕获
    • 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();}

优点

  1. 线程安全:使用互斥锁保护初始化过程
  2. 异常安全:使用 RAII 和 try-catch 处理文件操作异常
  3. 崩溃恢复友好:独立记录崩溃信息,便于问题定位
  4. 配置灵活:提供详细的配置选项
  5. 跨平台:统一接口,屏蔽平台差异

这个包装器特别适合需要稳定日志记录和崩溃分析的服务器程序或关键应用。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/18 7:03:34

MPU6050设备ID异常排查与I2C通信问题解决

1. MPU6050芯片设备ID不匹配的常见现象当你在使用MPU6050六轴传感器模块时&#xff0c;可能会遇到一个令人困惑的问题&#xff1a;读取到的设备ID与官方文档中标注的0x68或0x69不符。这种情况在实际项目中并不少见&#xff0c;我最近在一个无人机飞控项目中就遇到了类似问题。1…

作者头像 李华
网站建设 2026/7/18 7:02:02

ExusData数据集深度解析:为什么它是机器人触觉感知的终极解决方案

ExusData数据集深度解析&#xff1a;为什么它是机器人触觉感知的终极解决方案 你是否在寻找一个能够真正提升机器人触觉感知能力的数据集&#xff1f;&#x1f914; ExusData数据集正是你需要的终极解决方案&#xff01;这个专门为机器人触觉感知设计的数据集&#xff0c;通过创…

作者头像 李华
网站建设 2026/7/18 7:01:55

从VAD SAMOS热梗看技术社区文化符号的构建与传播

1. 项目缘起&#xff1a;一个“梗”的诞生与我的技术好奇心最近&#xff0c;一个名为“VAD SAMOS - SALOFOREVER”的短语在网络上悄然流行起来。说实话&#xff0c;第一次看到这个标题时&#xff0c;我有点摸不着头脑。它不像一个标准的项目名称&#xff0c;更像是一个内部代号…

作者头像 李华