You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关闭日志时spdlog::get("app")触发访问违规问题求助

问题描述

尝试在应用优雅关闭前停止日志记录,但调用spdlog::get时触发了访问违规。相关代码如下:

void stopLog()
{
    auto log = spdlog::get("app"); //此处触发访问违规
    log->critical("app ends");
    log->flush();
    spdlog::shutdown();
}
//调用stopLog关闭日志
MainComponent::~MainComponent()
{
    stopLog();
}
原因分析与解决方案

核心原因

访问违规的本质是spdlog::get("app")返回了空指针,或是对应的logger实例已被销毁/释放。常见触发场景:

  • 目标logger实例此前已被手动销毁
  • 全局对象析构顺序冲突:MainComponent的析构发生在spdlog全局logger实例销毁之后,此时调用spdlog::get会访问已释放的内存空间。

可行解决方案

  1. 提前缓存logger实例
    在应用初始化阶段就获取并保存logger的指针/引用,避免在析构阶段调用spdlog::get:
// 全局或类成员变量保存logger实例
std::shared_ptr<spdlog::logger> g_app_logger;

// 应用初始化时执行
void initLog()
{
    g_app_logger = spdlog::get("app");
    // 校验初始化结果
    if (!g_app_logger)
    {
        // 处理logger未创建的异常情况
    }
}

void stopLog()
{
    if (g_app_logger)
    {
        g_app_logger->critical("app ends");
        g_app_logger->flush();
    }
    spdlog::shutdown();
}
  1. 调整析构顺序
    确保MainComponent的析构发生在spdlog全局资源释放之前。如果MainComponent是全局对象,可改为局部对象,或是调整全局对象的定义顺序(C++中全局对象析构顺序与构造顺序相反)。

  2. 增加空指针检查
    调用spdlog::get后立即校验返回值,避免空指针访问:

void stopLog()
{
    auto log = spdlog::get("app");
    if (log) // 先判断是否为空
    {
        log->critical("app ends");
        log->flush();
    }
    spdlog::shutdown();
}
  1. 使用spdlog全局日志接口
    若无需指定特定logger,直接调用spdlog的全局日志函数,跳过spdlog::get步骤:
void stopLog()
{
    spdlog::critical("app ends");
    spdlog::flush_all();
    spdlog::shutdown();
}

内容的提问来源于stack exchange,提问作者kokkerspåniel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 06:16:09