【问题标题】:ld: duplicate symbol. g++ld:重复符号。克++
【发布时间】:2010-10-08 10:22:18
【问题描述】:

好的,我正在尝试了解 g++ 和库。我有一些文件已编译到库中

来自制作文件

$(CC) -fPIC -c -o $@ $< -O2 -D__PS2

然后

$(CC) -shared -o $@ $(OBJ_FILES) -O2 -D__PS2

这编译得很好。

来自使用 lib 的程序

$(CC) -c -o $@ $< -I./

编译正常

$(CC) -o $@ $(OBJ_FILES) I./ -Llib -mootPS2lib.so

将 obj 链接在一起,然后 BOOM!

ld:在 object_files/foo.o 和 object_files/main.o 中重复符号 Moot::loggerInstance()

foo.hpp

//include guards
#include <Moot/Logger.hpp>
class Foo
{
public:
    void show();
}

foo.cpp

 #include "Foo.hpp"
 void Foo::show() { Moot::loggerInstance().turnLoggerOn(true); }

main.cpp 只包含 foo 并调用 show 方法。

感谢您的帮助。

更新 我对问题的细节不了解,抱歉。

通过将其设为静态库,我已使其在 Windows 上运行。

Logger.hpp 看起来像这样。 * 它还没有完成,所以我知道有一些东西丢失了。但它有效。

#ifndef MOOT_LOGGER_HPP
#define MOOT_LOGGER_HPP

#include <Moot/Platform.hpp>
#include <Moot/Utilities.hpp>
#include <iostream>
#include <fstream>
#include <string>

namespace Moot
{
    //! Outputs info to a text file. By default the logger is off.
    //! On the PS2 cout is used to output info onto the screen.
    class Logger
    {
        Logger()
        {
            std::ofstream logfile;
            logfile.open ("logfile.txt", std::ios::trunc);
            logfile << "LogFile - most recent at the bottom\n";
            logfile << "-----------------------------------\n \n";
            logfile.close();

            m_isLoggerOn = false;
        }


        Logger(const Logger&);
        Logger& operator=(const Logger&);

        ~Logger() {}

        bool m_isLoggerOn;

        template <typename T>
        void logMessage(T type)
        {
            # if (MOOT_ON_PS2)
                std::cout << type;
            # else
                std::ofstream logfile;
                logfile.open ("logfile.txt", std::ios::in | std::ios::app);
                logfile << type;
                logfile.close();
            #endif
        }


        //! Overiden << to allow you string together types.
        template <typename T>
        Logger& operator<< (T type) 
        {
            if (m_isLoggerOn) logMessage(type);

            return *this;
        }


        //! Overiden << to allow you string together types.
        Logger& operator<< (std::wstring wideStr)
        {
            if (m_isLoggerOn) logMessage(Moot::Utilities::convertWstringToString(wideStr));

            return *this;
        }

    public:

        //! Instance of the logger.
        static Logger& getInstance()
        {
            static Logger log;
            return log;
        }

        //! Switch Logging off or on. It is set to off by default.
        void turnLoggerOn(bool setLogger)
        {
            m_isLoggerOn = setLogger;
        }

    }; // Logger


    Logger& loggerInstance()
    {
        return Logger::getInstance();
    }


    //! Convenience variables
    namespace {
        Logger& lStart    = loggerInstance();
        const char lEnd   = '\n';
    }
} // Moot


#endif

【问题讨论】:

  • 问题似乎位于Logger.hpp。你能解释一下loggerIstance()的定义吗?
  • 对不起,我应该包括记录器。谢谢
  • 请注意您没有保护 Foo.hpp 防止双重包含。

标签: c++ g++


【解决方案1】:

一种解决方案是声明loggerInstance 内联。

这是inline关键字的真正用途。如果编译器愿意,您的函数将被内联,但不会被定义两次。

【讨论】:

    【解决方案2】:

    我希望您的 logger.h 文件中有类似的内容:

    namespace Moot
       {
       LoggerInstance &loggerInstance()
          {
          static LoggerInstance myself:
          return myself;
          }
       }
    

    这是实现单例的常用方法(尽管不是完全线程安全的)。

    解决方案是将 loggerInstance 的实现移动到单独的 .CPP 文件中。

    【讨论】:

    • 我就是这么做的,我试试看。
    【解决方案3】:

    确保您的标头只包含一次。即

    #ifndef M_H
    #define M_H
    //Your code
    #endif
    

    在我看来,标题是双重包含的。

    【讨论】:

    • 我有链接保护,这是我检查的第一件事。这让我有点困惑。
    【解决方案4】:

    看起来您实际上不需要在您的 Foo.hpp 中包含 Logger.hpp 。尝试将其包含在实际使用 Logger 对象的Foo.cpp 中。

    作为一般规则,除非您绝对需要,否则不要在标题中包含内容,因为这样做会创建不需要存在的依赖项。即

    foo.hpp

    #ifndef FOO_HPP
    #define FOO_HPP
    
    class Foo 
    { 
    public: 
        void show(); 
    }
    
    #endif // FOO_HPP
    

    foo.cpp

     #include "Foo.hpp" 
     #include <Moot/Logger.hpp>
     void Foo::show() { Moot::loggerInstance().turnLoggerOn(true); } 
    

    【讨论】:

    • 啊,我明白了,我已经在标题中包含了所有内容:/
    • @PhilCK:真正的问题是头文件中Moot::loggerInstance 的(非内联)定义。对于非内联函数,程序中只能出现一个定义,但在“Foo.hpp”头文件中包含“Moot/Logger.hpp”会导致“Moot/Logger.hpp”文件同时包含在两个.cpp中文件和Moot::loggerInstance 函数的两个定义。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-23
    • 1970-01-01
    • 1970-01-01
    • 2012-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多