c++ 工厂方法上的spdlog崩溃

bfhwhh0e  于 2023-02-01  发布在  其他
关注(0)|答案(2)|浏览(298)

昨天我已经开始将spdlog包含到我的一个个人项目中用于日志记录。到目前为止,我在让库包含工作方面遇到了一些问题,但这些问题现在已经完全解决了。
现在一切都很好地编译了,所有的头文件都找到了,但是当我试图创建日志记录器或者简单地设置记录模式时,代码会因为分段错误而崩溃,更具体地说,无论我在程序中第一次从spdlog名称空间调用哪个函数都会导致崩溃。
我有一个从spdlog(基于this repo)中抽象一些部分的类,如下所示:

//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。(我知道spdlog是C11,但我需要14以后的特性,另外,设置-std=c11也不能解决这个问题)和截至昨天的spdlog的最新版本(直接从他们的GitHub repo中提取)。
编辑:根据评论中的要求,我创建了一个小项目(单个cpp文件,像在真实的项目中那样包含spdlog,或者与从main.cpp文件引用并相应链接到的真实项目中相同的代码和库设置),旨在重现该问题,以下是我的发现:* 直接在可执行文件中使用spdlog时不存在此问题 * 如果将Logger类移到共享库中并从那里链接到,则存在此问题
下面是我收到的错误消息:

Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)

以及我正在使用的CMakeLists.txt文件(我将库中的一个嵌套到项目中,因为到目前为止CLion不支持“同一解决方案中的多个项目”,例如VS):#CMakeLists.txt用于库cmake_minimum_required(版本3.10致命错误)

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)
q3qa4bjr

q3qa4bjr1#

您对两个记录器使用相同的名称,当您运行它时,您将得到:

$ ./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");
qoefvg9y

qoefvg9y2#

问题可能是spdlog的静态对象被定义了两次--从共享库内部和从包含日志头的客户端代码(包括spdlog. h)。
尝试从头文件和中删除对spdlog. h的include(并使用spdlog::logger的前向声明),并仅包含Logger. cpp文件中的spdlog. h。

    • 编辑**:

不能跨编译单元边界正向声明spdlog::logger。解决方案是用logger.cpp中定义的某个简单类 Package logger,并仅将其导出到logger.h中

相关问题