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

如何在多源文件间共享spdlog Logger对象避免段错误?

段错误原因及解决方法

段错误原因

你在main函数中创建的myLogger是局部栈对象,并没有注册到spdlog的全局日志器注册表中。spdlog::get("myLogger")只能返回已注册到全局注册表的日志器指针,因此这里会返回nullptr。后续调用myLogger->info()时,对空指针进行解引用,直接触发段错误。

正确配置方案

方案1:将日志器注册到spdlog全局注册表

通过std::make_shared创建日志器的智能指针,再调用spdlog::register_logger将其注册到全局注册表,这样其他文件就能通过spdlog::get获取到有效指针。

修改后的foo.cpp:

#include "bar.h"

#include "spdlog/spdlog.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include "spdlog/sinks/basic_file_sink.h"

int main()
{
    // Create log sinks w/ destinations
    auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
    auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>("logs/myLogFile.log", true);
    
    // Format logging statements
    console_sink->set_pattern("[%Y-%m-%d %H:%M:%S] [%n] [%^%l%$] %v");
    file_sink->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [Thread:%t] [%n] [%l] %v");

    // 创建智能指针形式的日志器并注册到全局注册表
    auto myLogger = std::make_shared<spdlog::logger>("myLogger", spdlog::sinks_init_list{console_sink, file_sink});
    spdlog::register_logger(myLogger);

    myLogger->info("Hello World! - foo.cpp");

    loggerTest();

    return 0;
}

bar.cpp保持不变即可,此时spdlog::get("myLogger")能正确获取到已注册的日志器指针,不会再触发段错误。

方案2:使用全局智能指针共享日志器

直接声明一个全局的std::shared_ptr<spdlog::logger>变量,在main中初始化后,其他源文件通过外部声明引用该变量。

修改后的foo.cpp:

#include "bar.h"

#include "spdlog/spdlog.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include "spdlog/sinks/basic_file_sink.h"

// 声明全局日志器指针
std::shared_ptr<spdlog::logger> g_myLogger;

int main()
{
    auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
    auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>("logs/myLogFile.log", true);
    
    console_sink->set_pattern("[%Y-%m-%d %H:%M:%S] [%n] [%^%l%$] %v");
    file_sink->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [Thread:%t] [%n] [%l] %v");

    // 初始化全局日志器指针
    g_myLogger = std::make_shared<spdlog::logger>("myLogger", spdlog::sinks_init_list{console_sink, file_sink});
    g_myLogger->info("Hello World! - foo.cpp");

    loggerTest();

    return 0;
}

修改后的bar.h:

#ifndef BAR_H
#define BAR_H

#include "spdlog/spdlog.h"

// 外部声明全局日志器指针
extern std::shared_ptr<spdlog::logger> g_myLogger;

void loggerTest();

#endif

修改后的bar.cpp:

#include "bar.h"

void loggerTest()
{
    // 直接使用全局日志器指针
    g_myLogger->info("Hello World! - bar.cpp");
}

注意事项

  • 如果你使用多线程环境,确保使用带有_mt后缀的sink(如stdout_color_sink_mt),保证线程安全。
  • 若使用全局注册表方案,程序退出时spdlog会自动清理已注册的日志器,无需手动释放;若使用全局变量方案,shared_ptr会自动管理生命周期。

内容的提问来源于stack exchange,提问作者user20278411

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 23:50:23