英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论