我正在使用log4cplus(从当前git master编译),但链接器出现 undefined 的参考错误。但是,这些错误仅在某些类中发生。

通常,每个类具有以下形式:

header (.h)

// ...
#include <log4cplus/loggingmacros.h>
// ...
// namespace(s)

class Example
{
public:
    // ...
private:
    // ...
    static const log4cplus::Logger logger;
};

来源(.cpp)
// includes

// namespace(s)

// implementations

const log4cplus::Logger Example::logger = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("Example"));

用法

记录器可在此类中使用:
LOG4CPLUS_WARN(logger,  "Ha, ha – whatever you try I wont work!");

在编译过程中,链接器会为引发 undefined 的引用错误
log4cplus::Logger::getInstance(std::string const&)


log4cplus::detail::macro_forced_log(log4cplus::Logger const&, int, std::string const&, char const*, int, char const*)

对于某些类(class)。我已经从工作类中复制了记录器部分:相同的结果。

用类成员替换静态记录器也不起作用-找不到getInstance()

解决此问题的解决方法是改用root-logger。这将编译/链接(即使getRoot()是同一类的一部分!?):
const log4cplus::Logger Example::logger = log4cplus::Logger::getRoot();

但随后存在 undefined 的参考错误
log4cplus::detail::macro_forced_log(...)

为确保没有错字,我使用了这些宏进行声明/定义:
#define LOG_DECL(name)      static const log4cplus::Logger logger
#define LOG_DEF(name)       const log4cplus::Logger name::logger = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT(#name))

相同的结果,以前起作用的那些也起作用,而那些不起作用的...也不起作用。

更多信息:
  • Log4cplus使用-llog4cplusSU链接(也已通过log4cplusS测试),并由git master
  • 编译
  • GCC 4.9 –使用了C++ 11
  • 用于构建项目
  • 的Eclipse CDT
  • Log4cplus在主
  • 中初始化
  • 所有类均使用相同的编译器和标志
  • 进行编译
  • 完全清理并构建项目
  • 所有文件的编译/链接方式与
  • 相同
  • const /不是const无效
  • nm <NAME>.o | grep -i log4cplus的结果:

    工作对象
                     U _ZN9log4cplus6detail16macro_forced_logERKNS_6LoggerEiRKSbIwSt11char_traitsIwESaIwEEPKciSB_
    0000000000000000 W _ZN9log4cplus6detail17macros_get_loggerERKNS_6LoggerE
                     U _ZN9log4cplus6detail18get_macro_body_ossEv
                     U _ZN9log4cplus6Logger11getInstanceERKSbIwSt11char_traitsIwESaIwEE
                     U _ZN9log4cplus6LoggerC1ERKS0_
                     U _ZN9log4cplus6LoggerD1Ev
    00000000000002c8 r _ZN9log4cplusL13ALL_LOG_LEVELE
    00000000000002ac r _ZN9log4cplusL13OFF_LOG_LEVELE
    00000000000002bc r _ZN9log4cplusL14INFO_LOG_LEVELE
    00000000000002b8 r _ZN9log4cplusL14WARN_LOG_LEVELE
    00000000000002c0 r _ZN9log4cplusL15DEBUG_LOG_LEVELE
    00000000000002b4 r _ZN9log4cplusL15ERROR_LOG_LEVELE
    00000000000002b0 r _ZN9log4cplusL15FATAL_LOG_LEVELE
    00000000000002c4 r _ZN9log4cplusL15TRACE_LOG_LEVELE
    00000000000002cc r _ZN9log4cplusL17NOT_SET_LOG_LEVELE
                     U _ZNK9log4cplus6Logger12isEnabledForEi
    

    Whith undefined reference :
                     U _ZN9log4cplus6detail16macro_forced_logERKNS_6LoggerEiRKSsPKciS7_
    0000000000000000 W _ZN9log4cplus6detail17macros_get_loggerERKNS_6LoggerE
                     U _ZN9log4cplus6detail18get_macro_body_ossEv
                     U _ZN9log4cplus6Logger11getInstanceERKSs
                     U _ZN9log4cplus6LoggerC1ERKS0_
                     U _ZN9log4cplus6LoggerD1Ev
    00000000000001ec r _ZN9log4cplusL13ALL_LOG_LEVELE
    00000000000001d0 r _ZN9log4cplusL13OFF_LOG_LEVELE
    00000000000001e0 r _ZN9log4cplusL14INFO_LOG_LEVELE
    00000000000001dc r _ZN9log4cplusL14WARN_LOG_LEVELE
    00000000000001e4 r _ZN9log4cplusL15DEBUG_LOG_LEVELE
    00000000000001d8 r _ZN9log4cplusL15ERROR_LOG_LEVELE
    00000000000001d4 r _ZN9log4cplusL15FATAL_LOG_LEVELE
    00000000000001e8 r _ZN9log4cplusL15TRACE_LOG_LEVELE
    00000000000001f0 r _ZN9log4cplusL17NOT_SET_LOG_LEVELE
                     U _ZNK9log4cplus6Logger12isEnabledForEi
    

    失败的最小类
    //////////////////////// Header ////////////////////////
    namespace so {
    namespace example {
    
    class FailingExample
    {
    public:
        FailingExample(other_ns::Config* config, other_ns::Command* cmd);
        bool updateData(uint8_t* dataPtr, uint32_t dataSize);
        virtual ~FailingExample();
    
    private:
        static const log4cplus::Logger logger;
    };
    }}
    
    
    //////////////////////// Source ////////////////////////
    namespace so {
    namespace example {
    
    FailingExample::FailingExample(other_ns::Config* config, other_ns::Command* cmd)
    {
    }
    
    bool FailingExample::updateData(uint8_t* dataPtr, uint32_t dataSize)
    {
        return true;
    }
    
    FailingExample::~FailingExample()
    {
    }
    
    // Undefined reference to getInstance() here
    const log4cplus::Logger FailingExample::logger = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("FailingExample"));
    
    }}
    

    最佳答案

    经过一段时间的调查,我找到了原因-解决方案。



    Log4cplus使用char / std::stringwchar / std::wstring,取决于是否定义了UNICODE

    例如。 LOG4CPLUS_TEXT()宏处理这些情况,将字符串转换为正确的字符串类型。

    问题

    尽管log4cplus是使用Unicode编译的(并且IDE显示了正确的预处理程序分支),但是链接程序无法链接正确的getInstance()或其他方法-有时在某些文件上!

    有时他成功了(使用std::wstring版本),然后失败了;找不到std::string版本,尽管实际上不应该使用它。

    在没有Unicode支持的情况下,编译log4cplus也不起作用(只是类型相反的问题...)

    原因

    项目中使用的第3方库在 header 丛林中具有以下代码:

    ...
    #ifdef ...
    #define UNICODE
    ...
    

    (注意:UNICODE不是由项目定义的)

    因此,库在 header 中的某个位置定义了UNICODE,如果发生这种情况,log4cplus将使用wstring方法,否则使用string

    这也解释了为什么某些文件可以工作而有些文件却失败的原因-取决于文件包含的头文件(以及这些文件头自己包括的文件...等等)。

    如果UNICODE使用wstring,则不使用string-由log4cplus类型,方法和宏使用(如上述LOG4CPLUS_TEXT())。如果此行为通过另一个库中某个深处的某个标志进行更改,则很好...

    解决方案

    我只需要在编译器标志中添加-DUNICODE就可以了! Log4cplus现在始终使用wchar-/ wstring -versions!

    无论如何,将来都将替换第三方库,也许会回到非unicode,但这是另一回事了。

    关于c++ - 未定义对Logger::getInstance()的引用-但仅在某些情况下,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32371683/

    10-11 19:40