如何在多源文件间共享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
相关产品推荐
相关产品推荐

