gabime / spdlog

Fast C++ logging library.
Other
23.93k stars 4.49k forks source link

`sinks_init_list` Using the wrong writing method in MSVC (but running normally) may result in Segmentation fault in other compilers #2976

Closed KunMengcode closed 8 months ago

KunMengcode commented 8 months ago
#0  0x000055555557318b in spdlog::logger::sink_it_ (this=0x555555786a70, msg=...)
    at /usr/work/Telephonist/../PublicLibrary/spdlog/include/spdlog/logger-inl.h:138
#1  0x00005555555c9b10 in spdlog::logger::log_it_ (this=0x555555786a70, log_msg=..., log_enabled=true,
    traceback_enabled=false) at /usr/work/Telephonist/../PublicLibrary/spdlog/include/spdlog/logger-inl.h:128
#2  0x00005555555c9a2f in spdlog::logger::log (this=0x555555786a70, loc=..., lvl=spdlog::level::warn, msg=...)
    at /usr/work/Telephonist/../PublicLibrary/spdlog/include/spdlog/logger.h:123
#3  0x00005555556870b5 in spdlog::logger::log<char [30]> (this=0x555555786a70, lvl=spdlog::level::warn, msg=...)
    at /usr/work/Telephonist/../PublicLibrary/spdlog/include/spdlog/logger.h:90
#4  0x0000555555686f59 in spdlog::logger::warn<char [30]> (this=0x555555786a70, msg=...)
    at /usr/work/Telephonist/../PublicLibrary/spdlog/include/spdlog/logger.h:248
#5  0x00005555556869fb in main () at /usr/work/Telephonist/Telephonist.cpp:18

OS :Ubuntu 24.04 GCC:gcc version 13.2.0 (Ubuntu 13.2.0-9ubuntu1)

tt4g commented 8 months ago

It is thought that release builds and debug builds are mixed, or that the application and spdlog have different compile options.

KunMengcode commented 8 months ago

@tt4g Indeed, release build and debug build are mixed, But the new problems I'm facing now.

#0  0x00005555555943f5 in spdlog::logger::sink_it_(spdlog::details::log_msg const&) ()
#1  0x000055555561f891 in spdlog::logger::log(spdlog::source_loc, spdlog::level::level_enum, fmt::v9::basic_string_view<char>) ()
#2  0x0000555555571c70 in main ()

Toolchain during Windows compilation : CMake+MSbuild Toolchain during Linux compilation : CMake+make+gcc

Previously, my main program used - D CMAKE_ BUILD_ TYPE=RELEASE and spdlog did not use this option. Just now I also set spdlog to - D CMAKE_ BUILD_ TYPE=RELEASE. Are there any other aspects of my build configuration that I haven't noticed? I think Windows and Linux should be similar at the moment

tt4g commented 8 months ago

If there is already spdlog installed on the Linux system, the built spdlog may not be loaded.

KunMengcode commented 8 months ago

I did not install spdlog in the system.Could it be because I didn't install something like libfmt9 for compilation?

tt4g commented 8 months ago

fmt library does not need to be installed on the system, because spdlog uses the bundled fmt unless the CMake variable SPDLOG_FMT_EXTERNAL is specified. Do you have a different version of fmt installed on your system than the one bundled with spdlog?

KunMengcode commented 8 months ago

I did not specify SPDLOG FMT INTERNATIONAL

tt4g commented 8 months ago

If so, the cause is unpredictable. The only thing I can think of is that there is a symbol in the Linux machine that causes a segmentation fault, or you are passing a dangling pointer to spdlog.

KunMengcode commented 8 months ago

The code for initializing 'spdlog:: logger' is as follows. Is there a problem with this type of writing?

LogOutput::LogOutput(std::string instance, LogConfiguration LogConfig)
{
    auto console_sink = std::make_shared<spdlog::sinks::stdout_sink_st>();
    auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_st>(LogConfig.fileOut_v, false);
    auto null_sink = std::make_shared<spdlog::sinks::null_sink_st>();

    console_sink->set_level(spdlog::level::level_enum(LogConfig.level_v));
    file_sink->set_level(spdlog::level::level_enum(LogConfig.level_v));

    console_sink->set_pattern(LogConfig.pattern_v);
    file_sink->set_pattern(LogConfig.pattern_v);

    spdlog::sinks_init_list sink_list;
    switch (LogConfig.sink_v)
    {
    case 0:
        sink_list = { console_sink };
        break;
    case 1:
        sink_list = { file_sink };
        break;
    case 2:
        sink_list = { file_sink, console_sink };
        break;
    case 3:
        sink_list = { null_sink };
        break;
    }

    log_sink = new spdlog::logger(instance, sink_list.begin(), sink_list.end());
    log_sink->flush_on(spdlog::level::info);
}
tt4g commented 8 months ago

I don't think it has anything to do with the logger initialization process, since what is crashing is the process of writing logs.

KunMengcode commented 8 months ago

case 0 , 1 and 3 . can all be correctly output in the console or file. Only sink_list = { file_sink, console_sink }; An error has occurred.

tt4g commented 8 months ago

spdlog::sinks_init_list is the alias of std::initializer_list<spdlog::sink_ptr>.

https://github.com/gabime/spdlog/blob/7cb90d1ab29f43b87e4e89e6707d02e9ddd6e8e7/include/spdlog/common.h#L143

As far as I can see from the cppreference (https://en.cppreference.com/w/cpp/utility/initializer_list), std::initializer_list cannot be copy assigned. Your program may have undefined behavior because it compiles code that is not in the C++ standard.

You should use std::vector<spdlog::sink_ptr>.

KunMengcode commented 8 months ago

Oh , oh , oh , oh , oh ! I changed the switch code snippet and the program resumed normal operation

switch (LogConfig.sink_v)
    {
    case 0:
        log_sink = new spdlog::logger(instance, {console_sink});
        break;
    case 1:
        log_sink = new spdlog::logger(instance, {file_sink});
        break;
    case 2:
        log_sink = new spdlog::logger(instance, {file_sink, console_sink});
        break;
    case 3:
        log_sink = new spdlog::logger(instance, {null_sink});
        break;
    }

Deleted spdlog::sinks_init_list sink_list; But I think what I wrote is the same, which is very puzzling

KunMengcode commented 8 months ago

Thank you for answering this question for me . This method is available in MSVC.(sink_list = { file_sink, console_sink };) MSVC may have done something in initializer_list . Different platforms have produced different results.