昨天,我已经开始在我的个人项目中包含spdlog,用于日志记录。到目前为止,我遇到了一些库包含的问题,但这些问题现在已经完全解决了。
现在一切都编译得很好,但是当我尝试创建记录器或简单地设置记录带有分段错误的代码崩溃的模式时,可以找到所有的头文件。更具体地说,无论我在程序中第一次从spdlog名称空间调用哪个函数都会导致崩溃。
我有一个类从spdlog中抽象出一些部分(基于this代码库),如下所示:
//Logger.hpp
#ifndef TE_LOGGER_HPP
#define TE_LOGGER_HPP
#include <spdlog/spdlog.h>
namespace te {
class Logger {
public:
static void Init();
inline static std::shared_ptr<spdlog::logger> &getCoreLogger() {
return sCoreLogger;
}
inline static std::shared_ptr<spdlog::logger> &getClientLogger() {
return sClientLogger;
}
private:
static std::shared_ptr<spdlog::logger> sCoreLogger;
static std::shared_ptr<spdlog::logger> sClientLogger;
};
}
#endif //TE_LOGGER_HPP
//Logger.cpp
#include "Logger.hpp"
#include <spdlog/sinks/stdout_color_sinks.h>
std::shared_ptr<spdlog::logger> te::Logger::sCoreLogger;
std::shared_ptr<spdlog::logger> te::Logger::sClientLogger;
void te::Logger::Init() {
//The first of any of the following three lines cause a crash
//no matter the order, regardless of the pattern used in set_pattern
spdlog::set_pattern("%v");
sCoreLogger = spdlog::stdout_color_mt("CORE");
sClientLogger = spdlog::stdout_color_mt("CORE");
sCoreLogger->set_level(spdlog::level::trace);
sClientLogger->set_level(spdlog::level::trace);
}从堆栈跟踪来看,问题似乎出在spdlog中的formatter类由于某种原因在库中的某处被设置为null。我在Ubuntu18.04上使用的是最新的CLion,C++14 (我知道spdlog是C++11,但是我需要14版本以后的特性,同样设置-std=c++11也不能解决这个问题)和最新版本的spdlog (直接从他们的GitHub库中提取)。
编辑:根据注释中的请求,我已经创建了一个小项目(单个cpp文件,像我在实际项目中所做的那样包含spdlog,或者与从main.cpp文件引用并相应链接到的实际项目中相同的代码和库设置),该项目旨在重现问题,以下是我的发现:*当我在可执行文件中直接使用spdlog时,问题不存在*如果将Logger类移动到共享库并从共享库链接到共享库,则会出现问题
下面是我收到的错误消息:
Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)和我正在使用的CMakeLists.txt文件(我将库的文件嵌套到项目中,因为到目前为止,CLion还不支持“同一解决方案中的多个项目”,例如VS ):#CMakeLists.txt for Library cmake_minimum_required(版本3.10 FATAL_ERROR)
project(TokenEngine VERSION 0.0.1 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 14)
set(SOURCE_FILES src/Application.cpp src/Application.hpp src/EntryPoint.hpp src/Logger.cpp src/Logger.hpp)
#include_directories("${CMAKE_CURRENT_SOURCE_DIR}/libs/")
add_library(TokenEngine SHARED ${SOURCE_FILES})
target_include_directories(TokenEngine PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/libs/spdlog-1.x/include")
#Expose the public API of the engine to any project that might use it
target_include_directories(TokenEngine PUBLIC include)
#CMakeLists.txt for top level project
cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
add_definitions(-DTE_PLATFORM_LINUX)
project(Build CXX)
add_subdirectory(TokenEngine)
add_subdirectory(Sandbox)发布于 2018-11-14 22:20:40
您为两个记录器使用了相同的名称,当您运行它时,您将得到:
$ ./logger
libc++abi.dylib: terminating with uncaught exception of type spdlog::spdlog_ex: logger with name 'CORE' already exists
Abort trap: 6如果您将客户端记录器的名称更改为其他名称,则可以正常工作:
sCoreLogger = spdlog::stdout_color_mt("CORE");
sClientLogger = spdlog::stdout_color_mt("CLIENT");发布于 2018-11-15 05:52:51
问题可能是spdlog的静态对象被定义了两次-从共享库内部和从包括记录器标头(包括spdlog.h)的客户端代码。
尝试从头文件中删除include to spdlog.h和(并且使用spdlog::logger的转发声明),并且只从Logger.cpp文件中包含spdlog.h。
编辑
不能跨编译单元边界向前声明spdlog::logger。解决方案是用logger.cpp中定义的一些简单类包装记录器,并且只将其导出到logger.h中
https://stackoverflow.com/questions/53301519
复制相似问题