关闭日志时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会访问已释放的内存空间。
可行解决方案
- 提前缓存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(); }
调整析构顺序
确保MainComponent的析构发生在spdlog全局资源释放之前。如果MainComponent是全局对象,可改为局部对象,或是调整全局对象的定义顺序(C++中全局对象析构顺序与构造顺序相反)。增加空指针检查
调用spdlog::get后立即校验返回值,避免空指针访问:
void stopLog() { auto log = spdlog::get("app"); if (log) // 先判断是否为空 { log->critical("app ends"); log->flush(); } spdlog::shutdown(); }
- 使用spdlog全局日志接口
若无需指定特定logger,直接调用spdlog的全局日志函数,跳过spdlog::get步骤:
void stopLog() { spdlog::critical("app ends"); spdlog::flush_all(); spdlog::shutdown(); }
内容的提问来源于stack exchange,提问作者kokkerspåniel
相关产品推荐
相关产品推荐

