英文:
segfault caused by a call to spdlog::get( "logger" )->info() in a file_event_handlers's callback
问题
以下是您要翻译的内容:
"以下程序由于段错误而崩溃。我找不到原因。我现在知道的是,两次对info()成员spdlog::get("basic_logger")->info("\nLogging started...");和spdlog::get("basic_logger")->info("Logging finished.");的调用都引起了问题(第一个引发了段错误,第二个引发了双重释放)。
一个最小的示例:
#include <chrono>
#include <exception>
#include <cstdio>
#include <fmt/core.h>
#include <fmt/chrono.h>
#include <spdlog/spdlog.h>
#include <spdlog/sinks/basic_file_sink.h>
int main()
{
spdlog::file_event_handlers handlers;
handlers.after_open = [](const spdlog::filename_t filename, std::FILE* const stream)
{
// Comment this line out to see the error caused by the before_close callback
spdlog::get("basic_logger")->info("\nLogging started...");
fmt::print(stream, "\n[{}] [{}] Logging started...\n",
std::chrono::system_clock::now(), filename);
};
handlers.before_close = [](const spdlog::filename_t filename, std::FILE* const stream)
{
spdlog::get("basic_logger")->info("Logging finished.");
fmt::print(stream, "[{}] [{}] Logging finished.\n",
std::chrono::system_clock::now(), filename);
};
try
{
auto logger = spdlog::basic_logger_st("basic_logger", "logs/basic-log.txt", true, handlers);
}
catch (const std::exception& sx)
{
fmt::print(stderr, "\nSomething went wrong during program startup: log file init failed: {}\n\n",
sx.what());
}
}
错误信息:
Segmentation fault (core dumped)
还有:
free(): double free detected in tcache 2
Aborted (core dumped)
构建命令:
g++ -std=c++23 -O3 -march=westmere -Wall -Wextra -Wpedantic -Wconversion -Wsign-conversion -Wshadow -fwhole-program -DNDEBUG `pkg-config --cflags spdlog` `pkg-config --libs spdlog` Temp.cpp -o runTemp
尽管print的调用没有引起任何问题,但我想用上面所示的info()调用替换它们,因为它记录了更多细节。"
英文:
The below program crashes due to a seg fault. I don't find a reason for this. All I know at the moment is that the two calls to info() member spdlog::get( "basic_logger" )->info( "\nLogging started..." ); and spdlog::get( "basic_logger" )->info( "Logging finished." ); are causing problems (the first one causes a segfault and the second one causes a double free).
A minimal example:
#include <chrono>
#include <exception>
#include <cstdio>
#include <fmt/core.h>
#include <fmt/chrono.h>
#include <spdlog/spdlog.h>
#include <spdlog/sinks/basic_file_sink.h>
int main( )
{
spdlog::file_event_handlers handlers;
handlers.after_open = [ ]( const spdlog::filename_t filename, std::FILE* const stream )
{ // Comment this line out to see the error caused by the before_close callback
spdlog::get( "basic_logger" )->info( "\nLogging started..." );
fmt::print( stream, "\n[{}] [{}] Logging started...\n",
std::chrono::system_clock::now( ), filename );
};
handlers.before_close = [ ]( const spdlog::filename_t filename, std::FILE* const stream )
{
spdlog::get( "basic_logger" )->info( "Logging finished." );
fmt::print( stream, "[{}] [{}] Logging finished.\n",
std::chrono::system_clock::now( ), filename );
};
try
{
auto logger { spdlog::basic_logger_st( "basic_logger", "logs/basic-log.txt", true, handlers ) };
}
catch ( const std::exception& sx )
{
fmt::print( stderr, "\nSomething went wrong during program startup: log file init failed: {}\n\n",
sx.what( ) );
}
}
The errors:
Segmentation fault (core dumped)
And also:
free(): double free detected in tcache 2
Aborted (core dumped)
Build command:
g++ -std=c++23 -O3 -march=westmere -Wall -Wextra -Wpedantic -Wconversion -Wsign-conversion -Wshadow -fwhole-program -DNDEBUG `pkg-config --cflags spdlog` `pkg-config --libs spdlog` Temp.cpp -o runTemp
The calls to print are not causing any issues though. However, I want to replace them with calls to info() as seen above because that logs more details.
答案1
得分: 1
你试图做的事情很遗憾不可能。不幸的是,你对 spdlog::basic_logger_st 的调用最终在 此处 结束:
static std::shared_ptr<spdlog::logger> create(std::string logger_name, SinkArgs &&... args)
{
/*[1]*/ auto sink = std::make_shared<Sink>(std::forward<SinkArgs>(args)...);
auto new_logger = std::make_shared<spdlog::logger>(std::move(logger_name), std::move(sink));
/*[2]*/ details::registry::instance().initialize_logger(new_logger);
return new_logger;
}
标记为 [1] 的那行代码是创建 sink 并调用你的 after_open 回调的代码,但 [2] 行实际上是将 logger 作为 basic_logger 可用的代码。
你将不得不将 after_open 中的日志语句提升到对 basic_logger_st 的调用之后。before_close 中的日志语句应该可以正常工作。
英文:
What you are trying to do is not possible, unfortunately. Your call to spdlog::basic_logger_st ends up here:
static std::shared_ptr<spdlog::logger> create(std::string logger_name, SinkArgs &&... args)
{
/*[1]*/ auto sink = std::make_shared<Sink>(std::forward<SinkArgs>(args)...);
auto new_logger = std::make_shared<spdlog::logger>(std::move(logger_name), std::move(sink));
/*[2]*/ details::registry::instance().initialize_logger(new_logger);
return new_logger;
}
The line marked with [1] is the one that creates the sink and calls your after_open callback, but line [2] is actually the one that makes the logger available as basic_logger.
You will have to hoist the log statement in after_open to the line after your call to basic_logger_st. The log statement in before_close should work without a problem.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论