gpt4 book ai didi

c++ - log4cxx:apr_pool_create_ex 中的段错误

转载 作者:行者123 更新时间:2023-12-01 21:23:34 29 4
gpt4 key购买 nike

我需要使用log4cxx对于 C++ 项目。但是我无法理解这个库的基本设置。这是我的最小尝试:

$ cat logger.cpp 
#include <log4cxx/logger.h>
#include <log4cxx/propertyconfigurator.h>
#include <log4cxx/helpers/properties.h>

static log4cxx::LoggerPtr ptr;

int main()
{
log4cxx::helpers::Properties prop;
prop.setProperty("log4j.rootLogger","DEBUG, A1");
prop.setProperty("log4j.appender.A1","org.apache.log4j.ConsoleAppender");
prop.setProperty("log4j.appender.A1.layout","org.apache.log4j.PatternLayout");
prop.setProperty("log4j.appender.A1.layout.ConversionPattern","%d{ABSOLUTE} %-5p [%c] %m%n");
log4cxx::PropertyConfigurator::configure(prop);

ptr = log4cxx::Logger::getLogger("API");
LOG4CXX_INFO(ptr , "test_info");
return 0;
}

然后我使用以下方法编译它:

$ g++ -g -o logger logger.cpp -llog4cxx

它失败了:

$ gdb ./logger
[...]
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff5f69dc9 in apr_pool_create_ex () from /lib64/libapr-1.so.0
Missing separate debuginfos, use: debuginfo-install apr-1.5.1-3.fc21.x86_64 apr-util-1.5.4-1.fc21.x86_64 cyrus-sasl-lib-2.1.26-19.fc21.x86_64 expat-2.1.0-10.fc21.x86_64 libdb-5.3.28-9.fc21.x86_64 libgcc-4.9.2-6.fc21.x86_64 libstdc++-4.9.2-6.fc21.x86_64 libuuid-2.25.2-3.fc21.x86_64 log4cxx-0.10.0-17.fc21.x86_64 nspr-4.10.8-1.fc21.x86_64 nss-3.19.1-1.0.fc21.x86_64 nss-softokn-freebl-3.19.1-1.0.fc21.x86_64 nss-util-3.19.1-1.0.fc21.x86_64 openldap-2.4.40-3.fc21.x86_64 zlib-1.2.8-7.fc21.x86_64
(gdb) bt
#0 0x00007ffff5f69dc9 in apr_pool_create_ex () from /lib64/libapr-1.so.0
#1 0x00007ffff7b26b58 in log4cxx::helpers::Pool::Pool() () from /lib64/liblog4cxx.so.10
#2 0x00007ffff7ae06ea in log4cxx::helpers::MutexException::formatMessage(int) () from /lib64/liblog4cxx.so.10
#3 0x00007ffff7ae0786 in log4cxx::helpers::MutexException::MutexException(int) () from /lib64/liblog4cxx.so.10
#4 0x00007ffff7b4a310 in log4cxx::helpers::synchronized::synchronized(log4cxx::helpers::Mutex const&) () from /lib64/liblog4cxx.so.10
#5 0x00007ffff7b5d9c8 in log4cxx::WriterAppender::close() () from /lib64/liblog4cxx.so.10
#6 0x00007ffff7ac979c in log4cxx::ConsoleAppender::~ConsoleAppender() () from /lib64/liblog4cxx.so.10
#7 0x00007ffff7ac98b9 in log4cxx::ConsoleAppender::~ConsoleAppender() () from /lib64/liblog4cxx.so.10
#8 0x00007ffff7aba247 in log4cxx::helpers::AppenderAttachableImpl::~AppenderAttachableImpl() () from /lib64/liblog4cxx.so.10
#9 0x00007ffff7b0494c in log4cxx::Logger::~Logger() () from /lib64/liblog4cxx.so.10
#10 0x00007ffff7b388b4 in log4cxx::spi::RootLogger::~RootLogger() () from /lib64/liblog4cxx.so.10
#11 0x00007ffff7b0429a in log4cxx::Logger::~Logger() () from /lib64/liblog4cxx.so.10
#12 0x00007ffff7b04429 in log4cxx::Logger::~Logger() () from /lib64/liblog4cxx.so.10
#13 0x0000000000401d6e in log4cxx::helpers::ObjectPtrT<log4cxx::Logger>::~ObjectPtrT (this=0x6031a0 <ptr>, __in_chrg=<optimized out>) at /usr/include/log4cxx/helpers/objectptr.h:100
#14 0x00007ffff6e38392 in __run_exit_handlers () from /lib64/libc.so.6
#15 0x00007ffff6e383e5 in exit () from /lib64/libc.so.6
#16 0x00007ffff6e1efe7 in __libc_start_main () from /lib64/libc.so.6
#17 0x0000000000401599 in _start ()

为记录器使用全局变量有什么根本错误?对我来说,这里使用单例模式确实有意义。

系统是:Fedora 21,具有:

$ rpm -qv log4cxx
log4cxx-0.10.0-17.fc21.x86_64

和:

$ g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/4.9.2/lto-wrapper
Target: x86_64-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-languages=c,c++,objc,obj-c++,fortran,ada,go,lto --enable-plugin --enable-initfini-array --disable-libgcj --with-isl=/builddir/build/BUILD/gcc-4.9.2-20150212/obj-x86_64-redhat-linux/isl-install --with-cloog=/builddir/build/BUILD/gcc-4.9.2-20150212/obj-x86_64-redhat-linux/cloog-install --enable-gnu-indirect-function --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux
Thread model: posix
gcc version 4.9.2 20150212 (Red Hat 4.9.2-6) (GCC)

最佳答案

更简单的尝试也会以完全相同的方式崩溃:

#include <log4cxx/logger.h>
#include <log4cxx/basicconfigurator.h>

static log4cxx::LoggerPtr ptr;

int main()
{
log4cxx::BasicConfigurator::configure();

ptr = log4cxx::Logger::getLogger("API");
return 0;
}

这种愚蠢的崩溃的最终原因非常深层次,与 log4cxx 中的基本设计缺陷有关(从误导性的尝试和理念开始,使 C++ 代码“看起来、感觉和工作像 Java”)。

最直接的原因是全局 LoggerPtr ptr 所持有的 Logger 的析构函数被调用太晚。到那时,APR 库(log4cxx 代码库所依赖的)将被解除,因此 synchronized::synchronized 构造函数调用(堆栈跟踪中的#4)必然会失败 - 之后某种崩溃是不可避免的。为什么代码必须跳过这样的环节来释放资源本身就是一个传奇,不值得在这里讨论。

问题本身与静态反初始化的顺序有关:APR 库被“太早”解雇,因为它实际上是通过静态单例初始化的,太晚了(在示例代码中,当LoggerPtr 实际上是给了一个 Logger 来保存)。

可以通过在退出 main() 之前添加此语句来“修复”示例代码(例如,在 return 0; 之前):

ptr = 0;

这将产生在 APR 库仍然“事件”时调用复杂资源释放序列的效果。

更通用的“解决方案”将涉及适当控制 APR 库的生命周期。 log4cxx 代码库具有分散在各处的静态 Meyers 单例,其中包括一个包装对 APR 库的 apr_initialize()apr_terminate() 的调用,但众所周知的“static initialization order fiasco ”使得很难将特定的单例安排为“最古老的”。 (必须从每个其他单例的构造函数中调用它。)因此,实际的“答案”是通过额外调用 apr_initialize() 来使 APR 库永远保持事件状态 - 比如,在 main() 的早期 - 与匹配的 apr_terminate() 保持平衡,并在程序终止时泄漏该特定资源。

请注意,该错误可以通过其他方式触发。事实上, this bug 变成了 a show-stopper for subsequent releases ,这可能就是整个 log4cxx 项目在十年前基本消亡的原因。

关于c++ - log4cxx:apr_pool_create_ex 中的段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31383751/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com